问题
I was reading asyncio documentation for task cancel and I came across this -
To cancel a running Task use the cancel() method. Calling it will cause the Task to throw a CancelledError exception into the wrapped coroutine. If a coroutine is awaiting on a Future object during cancellation, the Future object will be cancelled.
cancelled() can be used to check if the Task was cancelled. The method returns True if the wrapped coroutine did not suppress the CancelledError exception and was actually cancelled.
I have a few questions here -
Is wrapped coroutine the coroutine in which cancel is called? Let's take an example here -
async def wrapped_coroutine(): for task in asyncio.Task.all_tasks(): task.cancel()
So
wrapped_coroutine()
is the wrapped coroutine where task will throw an exception?When will this exception be thrown? And where?
What does suppress the exception mean here? Does it mean this -
async def wrapped_coroutine(): for task in asyncio.Task.all_tasks(): task.cancel() try: await task except asyncio.CancelledError: print("Task cancelled")
If not, please provide an example on how to suppress this exception.
And an unrelated(it's related to cancelling tasks), how do I retrieve exceptions out of these tasks when I'm cancelling these so I don't see this -
Task exception was never retrieved future:
Is it before task.cancel()
or in try
before await task
(in the above example) ?
回答1:
Looking at the code in the example given in the documentation https://docs.python.org/3/library/asyncio-task.html#asyncio.Task.cancel:
async def cancel_me():
print('cancel_me(): before sleep')
try:
# Wait for 1 hour
await asyncio.sleep(3600)
except asyncio.CancelledError:
print('cancel_me(): cancel sleep')
raise
finally:
print('cancel_me(): after sleep')
async def main():
# Create a "cancel_me" Task
task = asyncio.create_task(cancel_me())
# Wait for 1 second
await asyncio.sleep(1)
task.cancel()
try:
await task
except asyncio.CancelledError:
print("main(): cancel_me is cancelled now")
asyncio.run(main())
Answering your questions:
- "Is the wrapped coroutine the coroutine in which cancel is called?"
No, the wrapped coroutine here iscancel_me()
;.cancel()
is called inmain()
. - "When will this exception be thrown? And where?"
This exception is thrown aftertask.cancel()
is called. It is thrown inside the coroutine, where it is caught in the example, and it is then re-raised to be thrown and caught in the awaiting routine. - "What does suppress the exception mean here?"
Ifcancel_me()
would not have re-raised the exception after catching it. As the documentation ofcancelled()
states: "The Task is cancelled when the cancellation was requested with cancel() and the wrapped coroutine propagated the CancelledError exception thrown into it." https://docs.python.org/3/library/asyncio-task.html#asyncio.Task.cancelled
来源:https://stackoverflow.com/questions/56052748/python-asyncio-task-cancellation