Reputation: 8833
How can I print the stacktrace of an exception object such as the return value of concurrent.futures.Future.exception()
? Most of the traceback
and sys
exception functions depend upon an implicit exception that is "currently being handled" (this includes sys.exc_info
, traceback.print_exc
, traceback.format_exc
). The exception has already been handled, and is returned as an object, so these are worthless to me. There are a couple of traceback
functions which take an exception argument, but they either give no stack trace output, or they require a traceback object as input, which I do not have. I could of course create a traceback object, but that object would not contain the information I need.
Yes, I am aware that there are lots of Q/A here about printing the stacktrace of an exception. I've searched through them. This question is completely distinct from those.
This is an example of what I'm trying to do.
with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
for idx in range(0, 10):
future = executor.submit(third_party_script.main)
threads.append(future)
for future in threads:
if(future.exception()):
print(magic_traceback_function(future.exception()))
How can I print the stacktrace of an exception object such as the return value of concurrent.futures.Future.exception()
?
Upvotes: 2
Views: 2469
Reputation: 2304
I was struggling with this until I discovered that with loguru you can actually use the @logger.catch
annotation to see the exception logs/stacktrace (and actually in a colorful way!), like so:
@logger.catch
def other_script():
...
with concurrent.futures.ThreadPoolExecutor() as executor:
for idx in range(0, 10):
executor.submit(other_script)
However, it might not help if you can't annotate the third party script. In any case, it helped me.
Upvotes: 1
Reputation: 1540
There is the exception
method which returns the exception raised by the call. So, you can get the traceback from it as from any other exception (Python 3.5+). Use traceback.TracebackException
for it (just replace ex
with your exception):
print("".join(traceback.TracebackException.from_exception(ex).format())
An extended example and other features to do this:
import traceback
try:
1/0
except Exception as ex:
print("".join(traceback.TracebackException.from_exception(ex).format()) == traceback.format_exc() == "".join(traceback.format_exception(type(ex), ex, ex.__traceback__)))
print("".join(traceback.TracebackException.from_exception(ex).format()))
The output will be something like:
True
Traceback (most recent call last):
File "untidsfsdfsdftled.py", line 29, in <module>
1/0
ZeroDivisionError: division by zero
Upvotes: 5
Reputation: 41169
You can get the exception to raise by calling future.result()
. As far as I know, it should contain the original traceback, too. So, you could catch the exception by putting future.result()
in a try block and print the traceback. There's also the __traceback__
attribute which may be helpful for you.
Upvotes: 2