Exception handling in Python - python

http://docs.python.org/library/imaplib.html states that:
exception IMAP4.error
Exception raised on any errors. The reason for the exception is passed to the constructor as a string.
What does "exception is passed to the constructor as a string" mean? What would the code look like that can print the reason.

Just use print str(exception).

You can specify the reason when constructing the exception yourself, and put it into a variable when catching the exception.
try:
raise imaplib.IMAP4.error('Some exception')
except imaplib.IMAP4.error, error:
print error

Related

How to assertRaises in unittest an exception caught in try except block?

In my production function:
def myfunction():
try:
do_stuff()
(...)
raise MyException("...")
except MyException as exception:
do_clean_up(exception)
My test fails, because the exception is caught in the try/except block
def test_raise(self):
with self.assertRaises(MyException):
myfunction()
self.assertRaises is never called.
How to guarantee that the exception is caught during testing?
The exception is never asserted
AssertionError: MyException not raised
This is because you caught the exception MyException direct in myFunction().
Comment out out the try-except clause and try again, test should pass.
assertRaises is used for uncaught errors. You can also re-raise in except block.
The exception is handled internally, so there is no external evidence that the exception is raised.
However, both MyException and do_clean_up are external names, which means you can patch them and make assertions about whether they do or do not get used. For example,
# Make sure the names you are patching are correct
with unittest.mock.patch('MyException', wraps=MyException) as mock_exc, \
unittest.mock.patch('do_clean_up', wraps=do_clean_up) as mock_cleanup:
myfunction()
if mock_exc.called:
mock_cleanup.assert_called()

usage of except and store error in a variable

I need to catch all the errors,exceptions, and everything that stops the execution of a code and store it in a variable.
I want something like this:
try:
Error generating code
except as err:
print err
But this doesnt work. Is there any other way to do the same?
except as err: doesn't work because the correct syntax is:
except TypeOfError as somename:
To catch any type of error, use Exception as the type,
it is the common base class for all non-exit exceptions in Python:
try:
# Error generating code
except Exception as err:
print(err)
err will be an instance of the actual exception that was raised,
you can see its correct type with type(err),
and it's attributes and methods with dir(err).
Keep in mind that it's recommended to use the most specific type of exception that may be raised.
See more details in Python's tutorial on error handling.

How to get exception message in Python properly

What is the best way to get exceptions' messages from components of standard library in Python?
I noticed that in some cases you can get it via message field like this:
try:
pass
except Exception as ex:
print(ex.message)
but in some cases (for example, in case of socket errors) you have to do something like this:
try:
pass
except socket.error as ex:
print(ex)
I wondered is there any standard way to cover most of these situations?
If you look at the documentation for the built-in errors, you'll see that most Exception classes assign their first argument as a message attribute. Not all of them do though.
Notably,EnvironmentError (with subclasses IOError and OSError) has a first argument of errno, second of strerror. There is no message... strerror is roughly analogous to what would normally be a message.
More generally, subclasses of Exception can do whatever they want. They may or may not have a message attribute. Future built-in Exceptions may not have a message attribute. Any Exception subclass imported from third-party libraries or user code may not have a message attribute.
I think the proper way of handling this is to identify the specific Exception subclasses you want to catch, and then catch only those instead of everything with an except Exception, then utilize whatever attributes that specific subclass defines however you want.
If you must print something, I think that printing the caught Exception itself is most likely to do what you want, whether it has a message attribute or not.
You could also check for the message attribute if you wanted, like this, but I wouldn't really suggest it as it just seems messy:
try:
pass
except Exception as e:
# Just print(e) is cleaner and more likely what you want,
# but if you insist on printing message specifically whenever possible...
if hasattr(e, 'message'):
print(e.message)
else:
print(e)
To improve on the answer provided by #artofwarfare, here is what I consider a neater way to check for the message attribute and print it or print the Exception object as a fallback.
try:
pass
except Exception as e:
print getattr(e, 'message', repr(e))
The call to repr is optional, but I find it necessary in some use cases.
Update #1:
Following the comment by #MadPhysicist, here's a proof of why the call to repr might be necessary. Try running the following code in your interpreter:
try:
raise Exception
except Exception as e:
print(getattr(e, 'message', repr(e)))
print(getattr(e, 'message', str(e)))
The repr(e) line will print Exception() and the str(e) line will print an empty string.
Update #2:
Here is a demo with specifics for Python 2.7 and 3.5: https://gist.github.com/takwas/3b7a6edddef783f2abddffda1439f533
I too had the same problem. Digging into this I found that the Exception class has an args attribute, which captures the arguments that were used to create the exception. If you narrow the exceptions that except will catch to a subset, you should be able to determine how they were constructed, and thus which argument contains the message.
try:
# do something that may raise an AuthException
except AuthException as ex:
if ex.args[0] == "Authentication Timeout.":
# handle timeout
else:
# generic handling
from traceback import format_exc
try:
fault = 10/0
except ZeroDivision:
print(format_exc())
Another possibility is to use the format_exc() method from the traceback module.
I had the same problem. I think the best solution is to use log.exception, which will automatically print out stack trace and error message, such as:
try:
pass
log.info('Success')
except:
log.exception('Failed')

MemoryError's message as str is empty in Python

This is a very silly question, but I'm running some tasks and catching their errors by:
try:
run_something()
except Exception as e:
handle_error(str(e))
I want the error message as a String because I'm using a UI and I want to display the error in a window.
The problem can be replicated as:
>>> import numpy as np
>>> np.range(1e10)
MemoryError Traceback (most recent call last)
<ipython-input-4-20a59c2069b2> in <module>()
----> 1 np.arange(1e10)
MemoryError:
However, if I try to catch the error and print its message (which I was hoping to be something like "MemoryError":
try:
np.arange(1e10)
except Exception as e:
print(str(e))
print("Catched!")
The only output I get is "Catched!". This is so stupid, I was doing some work with UI's and threading, and took me a while to realise that the problem was a memory error with no message at all.
Is the MemoryError the only Exception that is translated to an empty string? Because if it is the case I can check it. If not, how to get its message as a String?
So you probably want to print the name of the exception class:
try:
np.arange(1e10)
except Exception as e: #not catch...
print(str(e.__class__.__name__))
print("Catched!")
Using str(e) only prints the "message" of the exception, which in your case was empty.
Note that you can obtain the arguments passed to the exception constructor via the args attribute:
In [4]: try:
...: raise ValueError(1,2,3)
...: except ValueError as e:
...: print('arguments:', e.args)
arguments: (1, 2, 3)
When call str(e) it returns the message of the Exception. Take an example -
NameError: name 'a' is not defined
^ ^
name message
The part before : is the name of the exception, whereas the part after it is the message (arguments).
In the case of MemoryError , as you can see in your example -
MemoryError:
does not have an error message , only the name of the exception , hence you get the empty string.
I am not sure if there are other Exceptions that do not have an exception, but I believe it would be very rare to find such exceptions. Maybe you can print both the exception's name as well as the message , if you really want to take care of the MemoryError (and maybe other such rare exceptions without messages) , something like -
print(type(e).__name__ , ':', str(e))
From the Python documentation (Version 2.7, I guess also applies to Python 3.x):
The base class for all built-in exceptions. It is not meant to be directly inherited by user-defined classes (for that, use Exception). If str() or unicode() is called on an instance of this class, the representation of the argument(s) to the instance are returned, or the empty string when there were no arguments.
It seems, that MemoryError gets no arguments, and thus according to this documentation does give an empty string back.
The exception can of course still be catched, because it can be catched by its type.
You can get the name of the exception class and print that.
This makes of course also a lot of sense, since look at that:
a = {}
try:
a['barrel']
except Exception as e:
print str(e)
Will print just 'barrel' -- what is not so helpful, so to add the class name of the exception is really a good idea:
...
except Exception as e:
print(e.__class__.__name + ': ' + (str(e)))

Python: Exception raised even when caught in try/except clause [duplicate]

This question already has answers here:
How can I more easily suppress previous exceptions when I raise my own exception in response?
(3 answers)
Closed 8 years ago.
In my code I want to catch an exception when it occurs, print some information abut the exception to the screen, and then end the script once I have done so. I tried to use something equivalent to the following code, but I don't understand why I get the traceback I do.
When executing:
try:
1 / 0
except ZeroDivisionError:
print("Exception: ZeroDivisionError")
raise Exception
Console reads:
Exception: ZeroDivisionError
Traceback (most recent call last):
File "<pyshell#19>", line 2, in <module>
1 / 0
ZeroDivisionError: division by zero
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<pyshell#19>", line 5, in <module>
raise Exception
Exception
I thought that if I catch the ZeroDivisionError, it would no longer be raised, and the only thing that would show is the raise Exception I do at the end, but both show in the console.
Why do they both show, and how do I alter the code so only the second shows, or is there a better way to achieve what I want?
The console shows the context here; when an exception is raised from an exception handler, Python attaches the active exception as the __context__ attribute and Python shows that context later on if the new exception is not being handled. If you don't want the context to be shown, you need to supply a cause instead; you can supply an empty cause with with raise ... from None:
try:
1 / 0
except ZeroDivisionError:
print("Exception: ZeroDivisionError")
raise Exception from None
Quoting the raise statement documentation:
The from clause is used for exception chaining: if given, the second expression must be another exception class or instance, which will then be attached to the raised exception as the __cause__ attribute (which is writable). If the raised exception is not handled, both exceptions will be printed[...]
A similar mechanism works implicitly if an exception is raised inside an exception handler: the previous exception is then attached as the new exception’s __context__ attribute[...]
And from the Exceptions documentation:
When raising (or re-raising) an exception in an except clause __context__ is automatically set to the last exception caught; if the new exception is not handled the traceback that is eventually displayed will include the originating exception(s) and the final exception.
When raising a new exception (rather than using a bare raise to re-raise the exception currently being handled), the implicit exception context can be supplemented with an explicit cause by using from with raise:
raise new_exc from original_exc
The expression following from must be an exception or None. It will be set as __cause__ on the raised exception. Setting __cause__ also implicitly sets the __suppress_context__ attribute to True, so that using raise new_exc from None effectively replaces the old exception with the new one for display purposes (e.g. converting KeyError to AttributeError), while leaving the old exception available in __context__ for introspection when debugging.
The default traceback display code shows these chained exceptions in addition to the traceback for the exception itself. An explicitly chained exception in __cause__ is always shown when present. An implicitly chained exception in __context__ is shown only if __cause__ is None and __suppress_context__ is false.

Categories