Are Python Exceptions (apart from SyntaxError) runtime errors? - python

If I understand correctly, when I run a Python program, the Python interpreter generates bytecode (the .pyc file that appears alongside the .py source) unless the source contains a syntax error.
Does the bytecode compiler generate any other exceptions or are all the other exceptions raised at runtime when the .pyc code is being executed?

Well, any exception type can technically be raised during runtime via raise <exception>. But I assume that you understand this and are asking what exceptions might be raised while Python interprets your code (before execution). There are actually quite a few:
SyntaxError: This is raised by the parser as it reads the code. It results from invalid syntax such as unbalanced parenthesis, using a keyword in the wrong place, etc.
IndentationError: This is a subclass of SyntaxError and is raised whenever your code has improper indentation. An example would be:
if condition:
line_indented_4_spaces
line_indented_3_spaces
TabError: This is a subclass of IndentationError and is raised when you inconsistently mix tabs and spaces in a source file.
SystemError: This is raised by the interpreter when an internal operation fails. Encountering one usually means that your Python installation is messed up and might need a reinstall.
MemoryError: This is similar to SystemError and can be raised when an internal operation fails for lack of memory.
All of these exceptions can be raised before your code even begins to execute. The first three are caused by a corrupt source file and can be resolved by simply fixing the syntax or indentation. The latter two however are raised by the interpreter itself for internal operations which fail. This means that they are rare, but also that they are more serious and not so easy to fix.

There is no compilation step typically when you're working with Python code so I would argue that all errors in Python, SyntaxErrors included, are runtime errors.
For example, lets write this file:
in xrange(5):
That's obviously just nonsense (we'll even name it nonsense.py), but lets fire up the interpreter:
$ python
>>> try:
... import nonsense
... except SyntaxError:
... print("A syntax error occurred at runtime!")
...
A syntax error occurred at runtime!
>>>
So there you have it - a SyntaxError was raised and caught at runtime, which, in my mind at least, indicates that it's a runtime error.

Related

How to catch exception clickhouse_driver dbapi?

I want to catch exception while executing scipts/connecting to base using clickhouse_driver-drive dbapi.
Can I catch errors codes and errors message like
errorcodes.lookup(e.pgcode)
and
e.diag.message_primary
from
psycopg2.import errorcodes?
Assuming you're using the most well known clickhouse-driver from here: https://pypi.org/project/clickhouse-driver (GitHub here: https://github.com/mymarilyn/clickhouse-driver), you must catch standard exceptions/errors. Most errors are defined in the clickhouse_driver.connection module, and they include socket errors, EOF errors, and other lower level errors.
Even though the dbapi for that project defines exception classes, none of them are actually used in the code. The driver does not in any way use the errors or error codes from the PostgreSQL psycopg2 project.

How to handle syntax Errors

So, we had instance in the past where code were broken in IOT devices because of syntax errors.
While there is exception handling in the code. I wanted to create a script to check and make sure that the codes compiles and run without syntax error, else the script replace the broken code by an earlier version.
I tried this
from delta_script import get_update
def test_function():
try:
get_update()
except SyntaxError as syntaxError:
replace_script("utility.py", syntaxError)
except Exception as ignored:
pass
However the problem it when it hit a SyntaxError, it just throw it on the screen and replace_script
because the exception happens on delta_script.py from which get_update() was imported.
So what's the solution in this case?
I have also another function
def compile():
try:
for file in compile_list:
py_compile.compile(file)
except Exception as exception:
script_heal(file, exception)
however in this one, it never report any exception, because I go and introduce syntaxError and the code still compile without reporting an error
Any one could help me figure out a better way to solve those two problems?
thanks,
SyntaxErrors occur at compile time, not run time, so you generally can't catch them. There are exceptions, involving run time compilation using eval/exec, but in general, except SyntaxError: is nonsensical; something goes wrong compiling the code before it can run the code that sets up the try/except to catch the error.
The solution is to not write syntactically invalid code, or if you must write it (e.g. to allow newer Python syntax only when supported) to evaluate strings of said code dynamically with eval (often wrapping compile if you need something more complicated than a single expression) or exec.

Which exception should I throw if a module is not the correct version?

This may have been asked before or I may be overly pedantic, but my own searches have come up empty.
Looking through the Python 2.x exceptions page, I'm not sure which one I should raise if my script determines that the __version__ of a module that's been imported, e.g. cv2, is not the correct version. For example, a script I'm working on requires OpenCV version 3; what's the best exception to raise in the following block if it determines that the version != 3?
import cv2
if not cv2.__version__.startswith('3'):
raise ValueError('OpenCV _3_ required')
You can create you own custom exception if the existing ones don't suffice.
class VersionError(Exception):
def __init__(self, msg):
Exception.__init__(self,msg)
You've got a lot of options depending on what you want to do with this exception... Generally, I'd expect the install scripts to handle setting up the appropriate versions of dependencies so I might think of this as a simple runtime assertion -- Therefore AssertionError may be appropriate.
This one is really nice -- You don't need an if statement, just an assert:
assert cv2.__version__.startswith('3'), 'OpenCV _3_ required'
My next bet would be to use RuntimeError as that is really meant to be a general exception that happens at runtime (and isn't usually meant to be caught)... It's a pretty general "Oh snap, something bad happened that we cannot recover from. Lets just spit out an error to let the user know what happened".

Which Python exception should I throw?

I'm writing some code to manipulate the Windows clipboard. The first thing I do is to try and open the clipboard with OpenClipboard() function from the Windows API:
if OpenClipboard(None):
# Access the clipboard here
else:
# Handle failure
This function can fail. So if it does, I would like to raise an exception. My question is, which of the standard Python exceptions should I raise? I'm thinking WindowsError would be the right one, but not sure. Could someone please give me a suggestion?
It is better to avoid raising standard exceptions directly. Create your own exception class, inherit it from the most appropriate one (WindowsError is ok) and raise it. This way you'll avoid confusion between your own errors and system errors.
Raise the windows error and give it some extra infomation, for example
raise WindowsError("Clipboard can't be opened")
Then when its being debugged they can tell what your windows error means rather than just a random windowserror over nothing.
WindowsError seems a reasonable choice, and it will record extra error information for you. From the docs:
exception WindowsError
Raised when a Windows-specific error occurs or when the error number does not correspond to an errno value. The winerror and strerror values are created from the return values of the GetLastError() and FormatMessage() functions from the Windows Platform API. The errno value maps the winerror value to corresponding errno.h values. ...

Really weird issue with shelve (python)

I create a file called foo_module.py containing the following code:
import shelve, whichdb, os
from foo_package.g import g
g.shelf = shelve.open("foo_path")
g.shelf.close()
print whichdb.whichdb("foo_path") # => dbhash
os.remove("foo_path")
Next to that file I create a directory called foo_package than contains an empty __init__.py file and a file called g.py that just contains:
class g:
pass
Now when I run foo_module.py I get a weird error message:
Exception TypeError: "'NoneType' object is not callable" in ignored
But then, if I rename the directory from foo_package to foo, and change the import line in foo_module.py, I don't get any error. Wtf is going on here?
Running Python 2.6.4 on WinXP.
I think you've hit a minor bug in 2.6.4's code related to the cleanup at end of program. If you run python -v you can see exactly at what point of the cleanup the error comes:
# cleanup[1] foo_package.g
Exception TypeError: "'NoneType' object is not callable" in ignored
Python sets references to None during the cleanup at the end of program, and it looks like it's getting confused about the status of g.shelf. As a workaround you could set g.shelf = None after the close. I would also recommend opening a bug in Python's bug tracker!
After days of hair loss, I finally had success using an atexit function:
import atexit
...
cache = shelve.open(path)
atexit.register(cache.close)
It's most appropriate to register right after opening. This works with multiple concurrent shelves.
(python 2.6.5 on lucid)
This is indeed a Python bug, and I've posted a patch to the tracker issue you opened (thanks for doing that).
The problem is that shelve's del method calls its close method, but if the shelve module has already been through cleanup, the close method fails with the message you see.
You can avoid the message in your code by adding 'del g.shelf' after g.shelf.close. As long as g.shelf is the only reference to the shelf, this will result in CPython calling the shelve's del method right away, before the interpreter cleanup phase, and thus avoid the error message.
It seems to be an exception in a shutdown function registered by the shelve module. The "ignored" part is from the shutdown system, and might get its wording improved sometime, per Issue 6294. I'm still hoping for an answer on how to eliminate the exception itself, though...
for me a simple shelve.close() on an unclosed one did the job.
shelve.open('somefile') returns a "persistent dictionary for reading and writing" object which i used throughout the app's runtime.
when I terminated the app I received the "TypeError" Exception as mentioned.
I plased a 'close()' call in my termination sequence and that seemed to fix the problem.
e.g.
shelveObj = shelve.open('fileName')
...
shelveObj.close()
OverByThere commented on Jul 17, 2018
This seems to be fixable.
In short open /usr/lib/python3.5/weakref.py and change line 109 to:
def remove(wr, selfref=ref(self), _atomic_removal=_remove_dead_weakref):
And line 117 to:
_atomic_removal(d, wr.key)
Note you need to do this with spaces, not tabs as this will cause other errors.

Categories