@@ -293,6 +293,8 @@ It is recommended that coroutines use ``try/finally`` blocks to robustly
293
293
perform clean-up logic. In case :exc: `asyncio.CancelledError `
294
294
is explicitly caught, it should generally be propagated when
295
295
clean-up is complete. Most code can safely ignore :exc: `asyncio.CancelledError `.
296
+ If a task needs to continue despite receiving an :exc: `asyncio.CancelledError `,
297
+ it should :func: `uncancel itself <asyncio.Task.uncancel> `.
296
298
297
299
Important asyncio components, like :class: `asyncio.TaskGroup ` and the
298
300
:func: `asyncio.timeout ` context manager, are implemented using cancellation
@@ -1064,6 +1066,36 @@ Task Object
1064
1066
:meth: `cancel ` and the wrapped coroutine propagated the
1065
1067
:exc: `CancelledError ` exception thrown into it.
1066
1068
1069
+ .. method :: cancelling()
1070
+
1071
+ Return the number of cancellation requests to this Task, i.e.,
1072
+ the number of calls to :meth: `cancel `.
1073
+
1074
+ Note that if this number is greater than zero but the Task is
1075
+ still executing, :meth: `cancelled ` will still return ``False ``.
1076
+ It's because this number can be lowered by calling :meth: `uncancel `,
1077
+ which can lead to the task not being cancelled after all if the
1078
+ cancellation requests go down to zero.
1079
+
1080
+ .. method :: uncancel()
1081
+
1082
+ Decrement the count of cancellation requests to this Task.
1083
+
1084
+ Returns the remaining number of cancellation requests.
1085
+
1086
+ This should be used by tasks that catch :exc: `CancelledError `
1087
+ and wish to continue indefinitely until they are cancelled again::
1088
+
1089
+ async def resilient_task():
1090
+ try:
1091
+ await do_work()
1092
+ except asyncio.CancelledError:
1093
+ asyncio.current_task().uncancel()
1094
+ await do_work()
1095
+
1096
+ Note that once execution of a cancelled task completed, further
1097
+ calls to :meth: `uncancel ` are ineffective.
1098
+
1067
1099
.. method :: done()
1068
1100
1069
1101
Return ``True `` if the Task is *done *.
0 commit comments