Just so that it has been mentioned: asyncio.Task
objects have the methods result
and exception
.
result
:
[...] if the coroutine raised an exception, that exception is
re-raised [...]
exception
:
[...] If the wrapped coroutine raised an exception that exception is
returned [...]
Given a simple setup (in Python 3.7 syntax):
import asyncio
tasks =[]
async def bad_test():
raise ValueError
async def good_test():
return
async def main():
tasks.append(asyncio.create_task(bad_test()))
tasks.append(asyncio.create_task(good_test()))
asyncio.run(main())
Using result
, one could do:
for t in tasks:
try:
f = t.result()
except ValueError as e:
logger.exception("we're all doomed")
Or, using exception
:
for t in tasks:
if isinstance(t.exception(), Exception):
logger.exception("apocalypse now")
However, both methods require the Task
to be done, otherwise:
If the Task has been cancelled, this method raises a CancelledError
exception.
(result): If the Task’s result isn’t yet available, this method raises a
InvalidStateError exception.
(exception): If the Task isn’t done yet, this method raises an InvalidStateError exception.
So, unlike the proposal in the other answer, the logging will not happen when the exceptions raise in the tasks, but rather when the tasks are evaluated after they completed.
except Exception:
instead ofexcept:
to avoid suppressingKeyboardInterrupt
and similar non-errors. – Sachsse