Python - Easy way to capture exception in try-except-else - python

In Python, we can use as to capture the exception instance in the except statement. However, there does not seem to have an easy way to do the same in an else statement after the try. To be more clear, see the code below.
try:
raise Exception('Foo')
except ValueError as valueError:
print(valueError)
print('I can capture the exception instance with "as" keyword')
else: # Cannot use "as" here
print('Some exception other than ValueError')
print('How can I capture the exception in order to, e.g. print its message?')
Any idea?

try:
raise Exception('Foo')
except ValueError as valueError:
print(valueError)
print('I can capture the exception instance with "as" keyword')
except Exception as e:
print(e)
print('Some exception other than ValueError')
else:
print('no exception raised')

Use multiple except clauses:
Either like this:
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except OSError as err:
print("OS error: {0}".format(err))
except ValueError:
print("Could not convert data to an integer.")
except:
print("Unexpected error:", sys.exc_info()[0])
raise
or clubbing exceptions together:
except (RuntimeError, TypeError, NameError):
pass

Related

How to print Exceptions of a nested loop?

I want to print all the exception statements from within the inner try to the catch of the outside try. Is there any way to do this without changing the inner try-catch block
def test_nested_exceptions():
try:
try:
raise AssertionError('inner error ')
except AssertionError as ae:
raise AssertionError("error in except")
finally:
raise AssertionError("error in finally")
except AssertionError as e:
print(e)
You can't access the error object in the finally block but you could get some details using the sys module as shown below.
import sys
def test_nested_exceptions():
try:
try:
raise AssertionError('inner error ')
except AssertionError as ae:
print(ae)
raise AssertionError("error in except")
finally:
print(sys.exc_info())
raise AssertionError("error in finally")
except AssertionError as e:
print(e)
test_nested_exceptions()

Is there a python tool that generates a coverage-like report but for exceptions a function will raise?

I'm looking for a tool that reports all the types of exceptions that could be raised from functions. i.e ones that is trying to explicitly handle.
If I had this example code, in a script or some function etc. I could run this tool and it would report OSError, ValueError, Exception as the output.
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except OSError as err:
print("OS error: {0}".format(err))
except ValueError:
print("Could not convert data to an integer.")
except:
print("Unexpected error:", sys.exc_info()[0])
raise

Python: When catching a generic (any) exception, how do I store the exception name in a variable?

I know I can store an exception name in a variable with this syntax:
try:
code
except TypeError as e:
logger.error(e)
except NameError as e:
logger.error(e)
How do I do the same for the generic except: message? I assume that this (which is the general idea) won't work:
try:
code
except as e:
logger.error(e)
You can you use type(e).__name__ to capture the name of any error you encounter, and access the message as you a normal variable, with e.message. All the built in errors (indexError, TypeError, etc.) are children of the class Exception, so they will be picked up. to save it as a variable named 'err':
try:
code
except Exception as e:
err = type(e).__name__
message = e.message
This will save the error type of any exception of the base python type Exception that you run into, using the built in __name__ variable
BaseException is the broadest type you can catch:
try:
# some code
except BaseException as e:
logger.error(e)
You are able to catch Exception:
import logging
try:
code
except TypeError as e:
logger.error(e)
except NameError as e:
logger.error(e)
except Exception as e:
logging.error(e)
I ran into this with Python 2, where old-style classes aren't caught by except Exception or except BaseException. I solved it by using sys.exc_info to access the current exception:
import sys
try:
code
except:
e = sys.exc_info()[1]
logging.error(e)

Try-except code block needs optimization

At below, I have a try-except block that I want to refactor it. As you see, it is not pythonic and not-maintainable.
try:
try:
foo()
except xError:
doSth()
raise
except:
exc_type = sys.exc_info()[0]
if exc_type == FooError:
doBlaBla()
else:
doFlaFla()
blablabla() # whatever the exceptions is, run this code block
foobar()
zoo()
...
I change that block as the below code;
try:
try:
foo()
except xError:
doSth()
raise
except FooError:
doBlaBla()
raise
except:
doFlaFla()
raise
blablabla() # This is where the problem happens for me.
foobar()
zoo()
...
As you can see, I need a except-finally like operation. It will not run when no exception raises but any exceptions. What do you advice ? How should I change this clode block ?
Why you've used innder try exempt block?
In my opinion, it is a good practice to put finally except statement, that will catch unexpected error.
So I suggest:
try:
fn()
except Exception1:
do stuff you want
except Exception 2:
do another stuff
except Exception as e:
# Here you will catch an unexpected error, and you can log it
raise UnknownError -> do stuff you want
Why not something like:
def others():
"""Other stuff to do when non-xError occurs."""
blablabla()
foobar()
zoo()
and then factor into a single try:
try:
foo()
except xError:
doSth()
raise
except FooError:
doBlaBla()
others()
except Exception:
doFlaFla()
others()
A bare except is usually a bad idea.
You can wrap your exception-code in a try-finally block, for example:
try:
try:
foo()
except xError:
doSth()
raise
# catch Exception to avoid catching system errors
except Exception as e:
try:
if isinstance(e, FooError):
doBlaBla()
else:
doFlaFla()
raise
finally:
# this will always run regardless of what you raise
Another approach could be something like this:
e = None
try:
try:
foo()
except xError:
doSth()
raise
except FooError as e:
doBlaBla()
except Exception as e:
doFlaFla()
raise
finally:
# this will always run regardless of what you raise
if e:
# exception took place...

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

Categories

Resources