What happens when an exception occurs in a module initialization - python

I have a module, and in this module I initialize some variables as soon as the module is imported.
my_mobule.py:
def _build_service():
# ...do some stuffs
_service = _build_service()
In this case, what will happen if the _build_service method raises an exception? And how my module can recover from an exception and try to invoke the _build_service again?
Thank you guys.

It's pretty similar to the behaviour should you call a function which raises an exception - if you don't handle the exception in the module itself, then it will be simply bump up the stack to whoever imported your module.
That would look like this:
>>> import my_mobule # sic
UhohError: something went wrong
If you have an opportunity to handle it in the module, you could do it like so:
try:
_service = _build_service()
except UhohError:
# your handling code here

Related

Is there a way to "un-raise" exception in python?

I don't have control over a python library that needlessly raises a certain exception.
Is there a way to handle it with a "placebo" Exception subclass? i.e.
class MyException(Exception):
def __init__(self, value):
# literally do nothing. return to program flow
pass
raises a certain exception
You have a certain exception, you should handle the exception by specifying the exception class in the except clause of a try-except block.
The placebo approach (i.e. except Exception...) is only going to silence other exceptions since exceptions typically derive from Exception or isn't going to work at all (with your new exception class) since the raised exception is apparently not derived from the new exception class.
Bear in mind:
Errors should never pass silently unless explicitly silenced
So I don't see why you would want to undo a raised exception without a try-except. The exception was not raised for nothing.
If you're hoping to avoid the use of try-except every time the function from this library is called, then you could write a wrapper function that wraps the call with a try-except, and then use the new function henceforth.
from somelib import func
from somelib import SomeException
def wrapper_func(*args, **kwargs):
try:
func(*args, **kwargs)
except SomeException:
pass
While the other answer is correct, if you're dealing with some strange/buggy module you can give fuckitpy a try!
Note that it is generally a very bad idea to let the exceptions silently pass through.
Anyhow, the basic way to use fuckitpy is (quoting from the docs):
import fuckit
#import some_shitty_module
fuckit('some_shitty_module')
some_shitty_module.some_function()
Also from the docs:
Still getting errors? Chain fuckit calls. This module is like violence: if it doesn't work, you just need more of it.
import fuckit
fuckit(fuckit('some_shitty_module'))
# This is definitely going to run now.
some_shitty_module.some_function()
fuckitpy (GitHub): https://github.com/ajalt/fuckitpy

Python raising NotADirectoryError

I'm trying to raise an error when a directory does not exist, before I open files in that directory. According to this response I should use the most specific Exception constructor for my issue, which I think is NotADirectoryError. But running the code below I get NameError: global name 'NotADirectoryError' is not defined. Thanks in advance for any help!
import os
if not os.path.isdir(baselineDir):
raise NotADirectoryError("No results directory for baseline.")
And if there's a better way to do this please suggest it, thanks.
You're likely using Python 2, which does not define NotADirectoryError. However, this is defined in Python 3, for exactly the purpose you're trying to use it for.
If you need to use Python 2, you'll need to define the error yourself through a class. Read through the docs about user-defined exceptions to learn about subclassing the Exception class and customizing it for your own needs, if necessary. Here's a very simple example:
class NotADirectoryError(Exception):
pass
This will take the string passed to it and print it out, just like you want.
The error message is pretty clear: NotADirectoryError hasn't been defined. If you are trying to make up your own exception, #MattDMo points you to how to go about it. If you want to use an existing exception, IOError seems most appropriate.
Import the exception if you are aware of which module it belongs to:
from my.exception.module import NotADirectoryError
If not, you must define this class:
class NotADirectoryError(Exception):
pass
Exceptions, generally, are classes. You have to create a NotADirectoryError class that is a subclass of something, probably exceptions.OSError since that's what the os module will raise in that case.

NameError: global name 'AlreadyExists' is not defined when using try/except within a function

I know many of these questions exist but I can't seem to find one that works for the problem I am having.
I have the following:
def function():
try:
# function to create a table on hbase
except AlreadyExists, ae:
print "WARN: " + ae.message
when I call it from another python script it gives me
NameError: global name 'AlreadyExists' is not defined
...but if I remove the def function() and run it on its own, it works and doesn't complain about the global name.
I tried putting global AlreadyExists and that didn't work. I also looked at this similar problem but I'm not sure how to apply it because it works on its own (without me having to import anything specific, but as soon as I wrap it in a function it fails).
Any suggestions?
Python only tries to access the name when an exception is thrown. When you ran the code outside of the function it probably didn't throw the exception and that's why you think it worked.
You need to import the AlreadyExists exception from wherever it lives.
change
from hbase import ttypes
...
except AlreadyExists, ae:
to
except ttypes.AlreadyExists, ae:
http://www.ros.org/doc/api/hbase/html/classhbase_1_1ttypes_1_1AlreadyExists.html

How do I raise a custom exception from a package __init__?

I have a package __init__.py that looks something like this:
import sys
__required_python_version = (2,6, 0)
if sys.version_info < __required_python_version:
this_version = '.'.join([str(x) for x in sys.version_info[0:3]])
required_version = '.'.join([str(x) for x in __required_python_version])
raise PythonVersionError(this_version, required_version)
class PythonVersionError(Exception):
def __init__(self, this_version, required_version):
self.this_version = this_version
self.required_version = required_version
def __str__(self):
return 'Python version %s is invalid. Must be at least %s' % (self.this_ver, self.required_ver)
While I'm certain there is a more elegant way to format those version strings and I could probably get by using a standard exception, my real question is how would I do something like this? Would the best approach be to move my custom exception into a separate file and import it? Or should I wrap the version check in a function that executes when the __init__ is run? I'm just looking for recommendations on the preferred approach.
Thanks
Since it looks like you won't have any user for that exception --
unless this module is to be used by other modules you are impleemnting as part of a larger system, I say you don't need a custom exception here.
There is very little to gain from it, apart from the error message given. Ay module trying to import yours would have to be aware of it, to catch the exception, or just let the program stop witha backtrace. Since be aware of it , it would need to import your module, it would just crash to a backtrace anyway -- wher ethe user can then read the error message.
For one to read the error message,a plain "Exception" stating it is the incorrect PythonVersin is as good as any custom exception.
On the technical side, Python would need to know about PythonVersionError before raising it: you need to put that code before you try to raise it inside the if block.
And finally, if you are building a larger system, and other parts of the system might try to catch PythonVersionError, the coorect thing to do is to put it in its own file/module, so that it becomes available to this module that will raise it, and any other modules that are importing this.
There seems to be something awkward here.
Is it really usefull to create a custom Exception class when it won't be reused anywhere else in other modules ? If everyone did this we would end up with every module defining it's own different (and probably incompatible) PythonVersionError class.
Why don't you use a standard existing exception ? For this one I would probably go for a standard RuntimeError exception.
OK, I know you don't want this answer, but anyway.
If I really wanted to do this at least I would define PythonVersionException class as a local instance of checking code to avoid polluting module namespace or any global namespace of other files of the module.

How to Determine The Module a Particular Exception Class is Defined In

Note: i edited my Q (in the title) so that it better reflects what i actually want to know. In the original title and in the text of my Q, i referred to the source of the thrown exception; what i meant, and what i should have referred to, as pointed out in one of the high-strung but otherwise helpful response below, is the module that the exception class is defined in. This is evidenced by the fact that, again, as pointed out in one of the answers below the answer to the original Q is that the exceptions were thrown from calls to cursor.execute and cursor.next, respectively--which of course, isn't the information you need to write the try/except block.
For instance (the Q has nothing specifically to do with SQLite or the PySQLite module):
from pysqlite2 import dbapi2 as SQ
try:
cursor.execute('CREATE TABLE pname (id INTEGER PRIMARY KEY, name VARCHARS(50)')
except SQ.OperationalError:
print("{0}, {1}".format("table already exists", "... 'CREATE' ignored"))
#
cursor.execute('SELECT * FROM pname')
while 1:
try:
print(cursor.next())
except StopIteration:
break
#
i let both snippets error out to see the exception thrown, then coded the try/finally blocks--but that didn't tell me anything about which module the exception class is defined. In my example, there's only a single imported module, but where there are many more, i am interested to know how an experienced pythonista identifies the exception source (search-the-docs-till-i-happen-to-find-it is my current method).
[And yes i am aware there's a nearly identical question on SO--but for C# rather than python, plus if you read the author's edited version, you'll see he's got a different problem in mind.]
the second [[exception was thrown]] from a python core module
False: it was thrown from a call to cursor.next, exactly like the first one was thrown from a call to cursor.execute -- it's hard to say why you're baldly asserting this counterfactual, but contrary to fact it nevertheless remains.
If you're speaking about, what module an exception class was defined in, as opposed to, as you say, where it was thrown from, that's a completely different thing of course:
try:
...whatever...
except Exception, e:
print "caught an exception defined in module", e.__class__.__module__
Built-in exceptions are actually defined in module exceptions, as this code will also tell you. Of course, once you have the module name (which this snippet gives you), you can further explore, if you wish, e.g. by obtaining the module object (just index sys.modules by module name), etc.
Usually, I just read the documentation. Part of the documentation for a Python module or function is a list of the exceptions it defines. If it doesn't list anything, I just assume I'm looking for a Python builtin exception.
By the way, the StopIteration exception is the standard way for any Python "iterable" object to signal that you have come to the end of the data it will provide to you. This loop:
cursor.execute('SELECT * FROM pname')
while 1:
try:
print(cursor.next())
except StopIteration:
break
Can be written as:
cursor.execute('SELECT * FROM pname')
for x in cursor:
print(x)
EDIT: I have to say that, despite my cheerful confidence that the exceptions would be documented, I cannot find such a list in the Python docstring help or web page help for dbapi2. In that case I guess I just do what you did: Google search for the name of the exception and see what pops out!
You could use python's inspect module and generic Exception handling like so:
from inspect import getmodule
try:
# attempt some task
except Exception, e:
print getmodule(e)
Which will spit out the module and its path like so:
<module 'some.module' from '/path/to/some/module.pyc'>
Usually I wrap the bare minimum that I can in a try..except block, e.g.:
try:
os.rename('foo', 'bar')
except EnvironmentError:
...
try:
open('bar')
except EnvironmentError:
...
This way I can handle each exception appropriately and separately.
Exception is somehow part of the function signature. The 1st thing to do is to read the documentation, the list of exception it can throw should be given. That's the case in most modules.
In your code, you should catch the minimum exception and just have one general catch at the top of your code (in your main for example) and print somewhere the traceback in order to know where unhandled exceptions comes from.
Then the right way to make sure that you didn't miss an exception is to write unit tests for your code and to cover every possible scenario.
I hope it helps

Categories