here's my code from python2 which needs to be ported:
try:
do_something_with_file(filename)
except:
exc_type, exc_inst, tb = sys.exc_info()
exc_inst.filename = filename
raise exc_type, exc_inst, tb
with above code, I can get the whole exception with the problematic input file by checking whether an exception has 'filename' attribute.
however python3's raise has been changed. this is what 2to3 gave me for above code:
except Exception as e:
et, ei, tb = sys.exc_info()
e.filename = filename
raise et(e).with_traceback(tb)
which gives me another error and I don't think filename attribute is preserved:
in __call__
raise et(e).with_traceback(tb)
TypeError: function takes exactly 5 arguments (1 given)
What I just want is passing exceptions transparently with some information to track the input file. I miss python2's raise [exception_type[,exception_instance[,traceback]]]
- How can I do this in python3?
You can set the __traceback__
attribute:
except Exception as e:
et, ei, tb = sys.exc_info()
ei.filename = filename
ei.__traceback__ = tb
raise ei
or call .with_traceback()
directly on the old instance:
except Exception as e:
et, ei, tb = sys.exc_info()
ei.filename = filename
raise ei.with_traceback(tb)
However, the traceback is already automatically attached, there is no need to re-attach it, really.
See the raise
statement documentation:
A traceback object is normally created automatically when an exception is raised and attached to it as the
__traceback__
attribute, which is writable.
In this specific case, perhaps you wanted a different exception instead, with context?
class FilenameException(Exception):
filename = None
def __init__(self, filename):
super().__init__(filename)
self.filename = filename
try:
something(filename)
except Exception as e:
raise FilenameException(filename) from e
This would create a chained exception, where both exceptions would be printed if uncaught, and the original exception is available as newexception.__context__
.
You don't need to do anything; in Python 3 re-raised exceptions automatically have a full traceback from where they were originally raised.
try:
do_something_with_file(filename)
except Exception as exc_inst:
exc_inst.filename = filename
raise exc_inst
This works because PyErr_NormalizeException
sets the __traceback__
attribute appropriately on catching an exception in an except
statement; see http://www.python.org/dev/peps/pep-3134/.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With