Python: try-catch with multiple excepts with almost identical code - python

I have somthing similar in my code below, where I have multiple except statements and all of them have to execute the someCleanUpCode() function. I was wondering if there is a shorter way to do it. Like a block that is only being executed when there was an exception. I can't use the finally block because that's also being executed when the try doesn't raise an error. And I only need to execute the someCleanUpCode() when there was an error. I first want to print the error and after that, run the someCleanUpCode()
try:
dangerousCode()
except CalledProcessError:
print "There was an error without a message"
someCleanUpCode()
except Exception as e:
print "There was an error: " +repr(e)
someCleanUpCode()

Assuming CalledProcessorError subclasses Exception (which should be the case):
try:
dangerous_code()
except Exception as e:
print "There was an error %s" % ("without an error" if isinstance(e, CalledProcessError) else repr(e))
some_cleanup_code()
or if you have more to do:
try:
dangerous_code()
except Exception as e:
try:
dangerous_code()
except Exception as e:
if isinstance(e, CalledProcessError):
print "There was an error without a message"
else:
print "There was an error: " +repr(e)
some_cleanup_code()

are you looking for something like this?
try:
1/0
except (ValueError, ZeroDivisionError) as e:
print e
# add some cleanup code here
>>>integer division or modulo by zero
This catches multiple exceptions

Related

Is there a way in python to execute a piece of code only if any exception is raised in a try/except block?

I have a try/except block with multiple except blocks. I want to be able to execute a piece of code only if any of the exceptions are raised. Kind of like the finally statement, but finally execute regardless of if an exception was raised or not. Do I just have to add that code to each except block?
You can do your own type checking in the exception handler to deal with type-specific and general code.
def it_will_end_in_tears():
raise ValueError("bad value")
try:
val = it_will_end_in_tears()
except (TypeError, ValueError) as e:
if isinstance(e, TypeError):
print("type error stuff")
elif isinstance(e, ValueError):
print("value error stuff")
print("common stuff")
finally:
print("finally")
Instead of copy+pasting the code into each except block, i would declare a boolean execute_code = False and set it to True in each of the except blocks. After the whole try/except, add if execute_code:, then implement the code to execute if an exception occurred once inside the if block.

Boolean 'not' in Python exception catching

I try to construct a except clause that catches everything except [sic] a particular type of exception:
try:
try:
asdjaslk
except not NameError as ne: #I want this block to catch everything except NameError
print("!NameError- {0}: {1}".format(ne.__class__, ne))
except Exception as e: #NameError is the only one that should get here
print("Exception- {0}: {1}".format(e.__class__, e))
The language accepts the not in the except clause, but does nothing with it:
>>> Exception- <type 'exceptions.NameError'>: name 'asdjaslk' is not defined
Is it possible to do this or should I reraise them?
You'll have to re-raise. An except statement can only whitelist, not blacklist.
try:
asdjaslk
except Exception as ne:
if isinstance(ne, NameError):
raise
The not NameError expression returns False, so you are essentially trying to catch:
except False:
but no exception will ever match a boolean instance.
The syntax allows for any valid Python expression, and the thrown exception is matched against the outcome of that expression. except SomeException if debug else SomeOtherException: is perfectly valid, for example.
You can can try this:
try:
# your code raising exceptions
except NameError:
# catch the exception you don't want to catch
# but immediately raise it again:
print("re-raising NameError- {0}: {1}".format(ne.__class__, ne))
raise
except Exception as e:
# handle all other exceptions here
print("catching Exception- {0}: {1}".format(e.__class__, e))
pass

Python nested try/except - raise first exception?

I'm trying to do a nested try/catch block in Python to print some extra debugging information:
try:
assert( False )
except:
print "some debugging information"
try:
another_function()
except:
print "that didn't work either"
else:
print "ooh, that worked!"
raise
I'd like to always re-raise the first error, but this code appears to raise the second error (the one caught with "that didn't work either"). Is there a way to re-raise the first exception?
raise, with no arguments, raises the last exception. To get the behavior you want, put the error in a variable so that you can raise with that exception instead:
try:
assert( False )
# Right here
except Exception as e:
print "some debugging information"
try:
another_function()
except:
print "that didn't work either"
else:
print "ooh, that worked!"
raise e
Note however that you should capture for a more specific exception rather than just Exception.
You should capture the first Exception in a variable.
try:
assert(False)
except Exception as e:
print "some debugging information"
try:
another_function()
except:
print "that didn't work either"
else:
print "ooh, that worked!"
raise e
raise by default will raise the last Exception.
raise raises the last exception caught unless you specify otherwise. If you want to reraise an early exception, you have to bind it to a name for later reference.
In Python 2.x:
try:
assert False
except Exception, e:
...
raise e
In Python 3.x:
try:
assert False
except Exception as e:
...
raise e
Unless you are writing general purpose code, you want to catch only the exceptions you are prepared to deal with... so in the above example you would write:
except AssertionError ... :

Forcing code flow to go to except block

I have:
try:
...
except Exception, e:
print "Problem. %s" % str(e)
However, somewhere in try, i will need it to behave as if it encountered an Exception. Is it un-pythonic to do:
try:
...
raise Exception, 'Type 1 error'
...
except Exception, e:
print "Problem. Type 2 error %s" % str(e)
I think this is a bad design. If you need to take some action if (and only if) an exception wasn't raised, that is what the else clause is there for. If you need to take some action unconditionally, that's what finally is for. here's a demonstration:
def myraise(arg):
try:
if arg:
raise ValueError('arg is True')
except ValueError as e:
print(e)
else:
print('arg is False')
finally:
print("see this no matter what")
myraise(1)
myraise(0)
You need to factor the unconditional code into finally and put the other stuff in except/else as appropriate.
I think what you are doing is "unPythonic". Trys should really only cover the small part (ideally one line) of the code which you expect might sometimes fail in a certain way. You should be able to use try/except/else/finally to get the required behaviour:
try:
#line which might fail
except ExceptionType: # the exception type which you are worried about
#what to do if it raises the exception
else:
#this gets done if try is successful
finally:
#this gets done last in both cases (try successful or not)

python: recover exception from try block if finally block raises exception

Say I have some code like this:
try:
try:
raise Exception("in the try")
finally:
raise Exception("in the finally")
except Exception, e:
print "try block failed: %s" % (e,)
The output is:
try block failed: in the finally
From the point of that print statement, is there any way to access the exception raised in the try, or has it disappeared forever?
NOTE: I don't have a use case in mind; this is just curiosity.
I can't find any information about whether this has been backported and don't have a Py2 installation handy, but in Python 3, e has an attribute called e.__context__, so that:
try:
try:
raise Exception("in the try")
finally:
raise Exception("in the finally")
except Exception as e:
print(repr(e.__context__))
gives:
Exception('in the try',)
According to PEP 3314, before __context__ was added, information about the original exception was unavailable.
try:
try:
raise Exception("in the try")
except Exception, e:
print "try block failed"
finally:
raise Exception("in the finally")
except Exception, e:
print "finally block failed: %s" % (e,)
However, It would be a good idea to avoid having code that is likely to throw an exception in the finally block - usually you just use it to do cleanup etc. anyway.

Categories

Resources