Could not catch raise for this case - python

I have a re-triable wrapper class in Python which helps other func to retry. Let's assume my class is just called Wrapper. Here's my rough implementation (not real code):
Wrapper:
while True:
try:
func()
except Exception as e:
pass
num_retry--
if num_try == 0
raise
When I use the wrapper, I do:
try:
// use Wrapper
except Exception as e:
// handle exception
But I found the except part doesn't capture the exception, why? Anything special in Python about raise?

The reason is because you already captured the exception previously when you indicated that it was ignored with the sentence pass into Wrapper. Then the exception will not go up to the first try since it will be ignored.
Remove the capture of the exepction into Wrapper, and only let the capture outside. But the correct is that you should capture the exception into Wrapper not outside of him.

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.

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

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)))

Categories