@@ -294,11 +294,13 @@ 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
296
297
- Important asyncio components, like :class: `asyncio.TaskGroup ` and the
298
- :func: `asyncio.timeout ` context manager, are implemented using cancellation
299
- internally and might misbehave if a coroutine swallows
300
- :exc: `asyncio.CancelledError `.
297
+ The asyncio components that enable structured concurrency, like
298
+ :class: `asyncio.TaskGroup ` and :func: `asyncio.timeout `,
299
+ are implemented using cancellation internally and might misbehave if
300
+ a coroutine swallows :exc: `asyncio.CancelledError `. Similarly, user code
301
+ should not call :meth: `uncancel <asyncio.Task.uncancel> `.
301
302
303
+ .. _taskgroups :
302
304
303
305
Task Groups
304
306
===========
@@ -1003,76 +1005,6 @@ Task Object
1003
1005
Deprecation warning is emitted if *loop * is not specified
1004
1006
and there is no running event loop.
1005
1007
1006
- .. method :: cancel(msg=None)
1007
-
1008
- Request the Task to be cancelled.
1009
-
1010
- This arranges for a :exc: `CancelledError ` exception to be thrown
1011
- into the wrapped coroutine on the next cycle of the event loop.
1012
-
1013
- The coroutine then has a chance to clean up or even deny the
1014
- request by suppressing the exception with a :keyword: `try ` ...
1015
- ... ``except CancelledError `` ... :keyword: `finally ` block.
1016
- Therefore, unlike :meth: `Future.cancel `, :meth: `Task.cancel ` does
1017
- not guarantee that the Task will be cancelled, although
1018
- suppressing cancellation completely is not common and is actively
1019
- discouraged.
1020
-
1021
- .. versionchanged :: 3.9
1022
- Added the *msg * parameter.
1023
-
1024
- .. deprecated-removed :: 3.11 3.14
1025
- *msg * parameter is ambiguous when multiple :meth: `cancel `
1026
- are called with different cancellation messages.
1027
- The argument will be removed.
1028
-
1029
- .. _asyncio_example_task_cancel :
1030
-
1031
- The following example illustrates how coroutines can intercept
1032
- the cancellation request::
1033
-
1034
- async def cancel_me():
1035
- print('cancel_me(): before sleep')
1036
-
1037
- try:
1038
- # Wait for 1 hour
1039
- await asyncio.sleep(3600)
1040
- except asyncio.CancelledError:
1041
- print('cancel_me(): cancel sleep')
1042
- raise
1043
- finally:
1044
- print('cancel_me(): after sleep')
1045
-
1046
- async def main():
1047
- # Create a "cancel_me" Task
1048
- task = asyncio.create_task(cancel_me())
1049
-
1050
- # Wait for 1 second
1051
- await asyncio.sleep(1)
1052
-
1053
- task.cancel()
1054
- try:
1055
- await task
1056
- except asyncio.CancelledError:
1057
- print("main(): cancel_me is cancelled now")
1058
-
1059
- asyncio.run(main())
1060
-
1061
- # Expected output:
1062
- #
1063
- # cancel_me(): before sleep
1064
- # cancel_me(): cancel sleep
1065
- # cancel_me(): after sleep
1066
- # main(): cancel_me is cancelled now
1067
-
1068
- .. method :: cancelled()
1069
-
1070
- Return ``True `` if the Task is *cancelled *.
1071
-
1072
- The Task is *cancelled * when the cancellation was requested with
1073
- :meth: `cancel ` and the wrapped coroutine propagated the
1074
- :exc: `CancelledError ` exception thrown into it.
1075
-
1076
1008
.. method :: done()
1077
1009
1078
1010
Return ``True `` if the Task is *done *.
@@ -1186,3 +1118,125 @@ Task Object
1186
1118
in the :func: `repr ` output of a task object.
1187
1119
1188
1120
.. versionadded :: 3.8
1121
+
1122
+ .. method :: cancel(msg=None)
1123
+
1124
+ Request the Task to be cancelled.
1125
+
1126
+ This arranges for a :exc: `CancelledError ` exception to be thrown
1127
+ into the wrapped coroutine on the next cycle of the event loop.
1128
+
1129
+ The coroutine then has a chance to clean up or even deny the
1130
+ request by suppressing the exception with a :keyword: `try ` ...
1131
+ ... ``except CancelledError `` ... :keyword: `finally ` block.
1132
+ Therefore, unlike :meth: `Future.cancel `, :meth: `Task.cancel ` does
1133
+ not guarantee that the Task will be cancelled, although
1134
+ suppressing cancellation completely is not common and is actively
1135
+ discouraged.
1136
+
1137
+ .. versionchanged :: 3.9
1138
+ Added the *msg * parameter.
1139
+
1140
+ .. deprecated-removed :: 3.11 3.14
1141
+ *msg * parameter is ambiguous when multiple :meth: `cancel `
1142
+ are called with different cancellation messages.
1143
+ The argument will be removed.
1144
+
1145
+ .. _asyncio_example_task_cancel :
1146
+
1147
+ The following example illustrates how coroutines can intercept
1148
+ the cancellation request::
1149
+
1150
+ async def cancel_me():
1151
+ print('cancel_me(): before sleep')
1152
+
1153
+ try:
1154
+ # Wait for 1 hour
1155
+ await asyncio.sleep(3600)
1156
+ except asyncio.CancelledError:
1157
+ print('cancel_me(): cancel sleep')
1158
+ raise
1159
+ finally:
1160
+ print('cancel_me(): after sleep')
1161
+
1162
+ async def main():
1163
+ # Create a "cancel_me" Task
1164
+ task = asyncio.create_task(cancel_me())
1165
+
1166
+ # Wait for 1 second
1167
+ await asyncio.sleep(1)
1168
+
1169
+ task.cancel()
1170
+ try:
1171
+ await task
1172
+ except asyncio.CancelledError:
1173
+ print("main(): cancel_me is cancelled now")
1174
+
1175
+ asyncio.run(main())
1176
+
1177
+ # Expected output:
1178
+ #
1179
+ # cancel_me(): before sleep
1180
+ # cancel_me(): cancel sleep
1181
+ # cancel_me(): after sleep
1182
+ # main(): cancel_me is cancelled now
1183
+
1184
+ .. method :: cancelled()
1185
+
1186
+ Return ``True `` if the Task is *cancelled *.
1187
+
1188
+ The Task is *cancelled * when the cancellation was requested with
1189
+ :meth: `cancel ` and the wrapped coroutine propagated the
1190
+ :exc: `CancelledError ` exception thrown into it.
1191
+
1192
+ .. method :: uncancel()
1193
+
1194
+ Decrement the count of cancellation requests to this Task.
1195
+
1196
+ Returns the remaining number of cancellation requests.
1197
+
1198
+ Note that once execution of a cancelled task completed, further
1199
+ calls to :meth: `uncancel ` are ineffective.
1200
+
1201
+ .. versionadded :: 3.11
1202
+
1203
+ This method is used by asyncio's internals and isn't expected to be
1204
+ used by end-user code. In particular, if a Task gets successfully
1205
+ uncancelled, this allows for elements of structured concurrency like
1206
+ :ref: `taskgroups ` and :func: `asyncio.timeout ` to continue running,
1207
+ isolating cancellation to the respective structured block.
1208
+ For example::
1209
+
1210
+ async def make_request_with_timeout():
1211
+ try:
1212
+ async with asyncio.timeout(1):
1213
+ # Structured block affected by the timeout:
1214
+ await make_request()
1215
+ await make_another_request()
1216
+ except TimeoutError:
1217
+ log("There was a timeout")
1218
+ # Outer code not affected by the timeout:
1219
+ await unrelated_code()
1220
+
1221
+ While the block with ``make_request() `` and ``make_another_request() ``
1222
+ might get cancelled due to the timeout, ``unrelated_code() `` should
1223
+ continue running even in case of the timeout. This is implemented
1224
+ with :meth: `uncancel `. :class: `TaskGroup ` context managers use
1225
+ :func: `uncancel ` in a similar fashion.
1226
+
1227
+ .. method :: cancelling()
1228
+
1229
+ Return the number of pending cancellation requests to this Task, i.e.,
1230
+ the number of calls to :meth: `cancel ` less the number of
1231
+ :meth: `uncancel ` calls.
1232
+
1233
+ Note that if this number is greater than zero but the Task is
1234
+ still executing, :meth: `cancelled ` will still return ``False ``.
1235
+ This is because this number can be lowered by calling :meth: `uncancel `,
1236
+ which can lead to the task not being cancelled after all if the
1237
+ cancellation requests go down to zero.
1238
+
1239
+ This method is used by asyncio's internals and isn't expected to be
1240
+ used by end-user code. See :meth: `uncancel ` for more details.
1241
+
1242
+ .. versionadded :: 3.11
0 commit comments