此节提纲的高级 asyncio API 能操控协程和任务。
协程 采用 async/await 句法声明是编写 asyncio 应用程序的首选方式。例如,以下代码片段打印 hello,等待 1 秒,然后打印 world:
>>> import asyncio >>> async def main(): ... print('hello') ... await asyncio.sleep(1) ... print('world') >>> asyncio.run(main()) hello world
注意,简单调用协程不会调度它的执行:
>>> main() <coroutine object main at 0x1053bb7c8>
要实际运行协程,asyncio 提供下列机制:
asyncio.run()
函数运行顶层入口点 main() 函数 (见以上范例)。
等待协程。以下代码片段将在等待 1 秒后打印 hello,然后打印 world 后于等待 another 2 秒:
import asyncio import time async def say_after(delay, what): await asyncio.sleep(delay) print(what) async def main(): print(f"started at {time.strftime('%X')}") await say_after(1, 'hello') await say_after(2, 'world') print(f"finished at {time.strftime('%X')}") asyncio.run(main())
期望输出:
started at 17:13:52 hello world finished at 17:13:55
asyncio.create_task()
函数并发运行协程如 asyncio
Tasks
.
让我们修改以上范例并运行 2
say_after
协程
concurrently
:
async def main(): task1 = asyncio.create_task( say_after(1, 'hello')) task2 = asyncio.create_task( say_after(2, 'world')) print(f"started at {time.strftime('%X')}") # Wait until both tasks are completed (should take # around 2 seconds.) await task1 await task2 print(f"finished at {time.strftime('%X')}")
注意,现在期望的输出展示片段运行速度比之前快了 1 秒:
started at 17:14:32 hello world finished at 17:14:34
asyncio.TaskGroup
类提供了更现代替代对于
create_task()
。使用此 API,范例最后变成:
async def main(): async with asyncio.TaskGroup() as tg: task1 = tg.create_task( say_after(1, 'hello')) task2 = tg.create_task( say_after(2, 'world')) print(f"started at {time.strftime('%X')}") # The wait is implicit when the context manager exits. print(f"finished at {time.strftime('%X')}")
计时和输出应该如同先前版本。
3.11 版新增:
asyncio.TaskGroup
.
我们说对象是
awaitable
object if it can be used in an
await
expression. Many asyncio APIs are designed to accept awaitables.
有 3 种主要类型的 awaitable 对象: 协程 , 任务 ,和 未来 .
协程
Python 协程是 awaitables 因此可以从其它协程等待:
import asyncio async def nested(): return 42 async def main(): # Nothing happens if we just call "nested()". # A coroutine object is created but not awaited, # so it *won't run at all*. nested() # Let's do it differently now and await it: print(await nested()) # will print "42". asyncio.run(main())
重要
In this documentation the term “coroutine” can be used for two closely related concepts:
a
协程函数
:
async def
函数;
a 协程对象 : an object returned by calling a 协程函数 .
任务
任务 被用于调度协程 concurrently .
When a coroutine is wrapped into a
Task
with functions like
asyncio.create_task()
the coroutine is automatically scheduled to run soon:
import asyncio async def nested(): return 42 async def main(): # Schedule nested() to run soon concurrently # with "main()". task = asyncio.create_task(nested()) # "task" can now be used to cancel "nested()", or # can simply be awaited to wait until it is complete: await task asyncio.run(main())
未来
A
Future
is a special
低级
awaitable object that represents an
eventual result
of an asynchronous operation.
When a Future object is awaited it means that the coroutine will wait until the Future is resolved in some other place.
Future objects in asyncio are needed to allow callback-based code to be used with async/await.
Normally there is no need to create Future objects at the application level code.
Future objects, sometimes exposed by libraries and some asyncio APIs, can be awaited:
async def main(): await function_that_returns_a_future_object() # this is also valid: await asyncio.gather( function_that_returns_a_future_object(), some_python_coroutine() )
A good example of a low-level function that returns a Future object is
loop.run_in_executor()
.
包裹
coro
协程
成
Task
并调度其执行。返回任务对象。
若
name
不是
None
,将它设为任务名称使用
Task.set_name()
.
可选仅关键词
context
自变量允许指定自定义
contextvars.Context
为
coro
以在其中运行。创建当前上下文副本当没有
context
被提供。
在循环中执行的任务的返回通过
get_running_loop()
,
RuntimeError
被引发若当前线程中没有正运行的循环。
注意
asyncio.TaskGroup.create_task()
是允许方便等待一组相关任务的较新替代。
重要
保存对此函数结果的引用,以避免任务在执行过程中消失。事件循环只保持任务的弱引用。在其它地方未引用的任务可能在任何时候被垃圾收集,甚至在完成之前。对于可靠 "激发并忘记" 的后台任务,把它们收集起来:
background_tasks = set() for i in range(10): task = asyncio.create_task(some_coro(param=i)) # Add task to the set. This creates a strong reference. background_tasks.add(task) # To prevent keeping references to finished tasks forever, # make each task remove its own reference from the set after # completion: task.add_done_callback(background_tasks.discard)
3.7 版新增。
3.8 版改变: 添加 name 参数。
3.11 版改变: 添加 context 参数。
可以轻松且安全地取消任务。当取消任务时,
asyncio.CancelledError
will be raised in the task at the next opportunity.
It is recommended that coroutines use
try/finally
blocks to robustly perform clean-up logic. In case
asyncio.CancelledError
is explicitly caught, it should generally be propagated when clean-up is complete. Most code can safely ignore
asyncio.CancelledError
.
The asyncio components that enable structured concurrency, like
asyncio.TaskGroup
and
asyncio.timeout()
, are implemented using cancellation internally and might misbehave if a coroutine swallows
asyncio.CancelledError
. Similarly, user code should not call
uncancel
.
Task groups combine a task creation API with a convenient and reliable way to wait for all tasks in the group to finish.
An
异步上下文管理器
holding a group of tasks. Tasks can be added to the group using
create_task()
. All tasks are awaited when the context manager exits.
3.11 版新增。
Create a task in this task group. The signature matches that of
asyncio.create_task()
.
范例:
async def main(): async with asyncio.TaskGroup() as tg: task1 = tg.create_task(some_coro(...)) task2 = tg.create_task(another_coro(...)) print("Both tasks have completed now.")
async with
statement will wait for all tasks in the group to finish. While waiting, new tasks may still be added to the group (for example, by passing
tg
into one of the coroutines and calling
tg.create_task()
in that coroutine). Once the last task has finished and the
async with
block is exited, no new tasks may be added to the group.
The first time any of the tasks belonging to the group fails with an exception other than
asyncio.CancelledError
, the remaining tasks in the group are cancelled. No further tasks can then be added to the group. At this point, if the body of the
async with
statement is still active (i.e.,
__aexit__()
hasn’t been called yet), the task directly containing the
async with
statement is also cancelled. The resulting
asyncio.CancelledError
will interrupt an
await
, but it will not bubble out of the containing
async with
语句。
Once all tasks have finished, if any tasks have failed with an exception other than
asyncio.CancelledError
, those exceptions are combined in an
ExceptionGroup
or
BaseExceptionGroup
(as appropriate; see their documentation) which is then raised.
Two base exceptions are treated specially: If any task fails with
KeyboardInterrupt
or
SystemExit
, the task group still cancels the remaining tasks and waits for them, but then the initial
KeyboardInterrupt
or
SystemExit
is re-raised instead of
ExceptionGroup
or
BaseExceptionGroup
.
If the body of the
async with
statement exits with an exception (so
__aexit__()
is called with an exception set), this is treated the same as if one of the tasks failed: the remaining tasks are cancelled and then waited for, and non-cancellation exceptions are grouped into an exception group and raised. The exception passed into
__aexit__()
, unless it is
asyncio.CancelledError
, is also included in the exception group. The same special case is made for
KeyboardInterrupt
and
SystemExit
as in the previous paragraph.
阻塞 delay 秒。
若 result 有提供,将它返回给调用者当协程完成时。
sleep()
始终挂起当前任务,允许其它任务运行。
将延迟设为 0,提供了允许运行其它任务的优化路径。长时间运行的函数可以通过使用这,以避免在函数的完整调用期间阻塞事件循环。
在 5 秒内每秒显示当前日期的协程范例:
import asyncio import datetime async def display_date(): loop = asyncio.get_running_loop() end_time = loop.time() + 5.0 while True: print(datetime.datetime.now()) if (loop.time() + 1.0) >= end_time: break await asyncio.sleep(1) asyncio.run(display_date())
3.10 版改变: 移除 loop 参数。
运行 可期待对象 在 aws sequence concurrently .
若任何可期待在 aws 是协程,自动作为 Task (任务) 被调度。
If all awaitables are completed successfully, the result is an aggregate list of returned values. The order of result values corresponds to the order of awaitables in aws .
若
return_exceptions
is
False
(default), the first raised exception is immediately propagated to the task that awaits on
gather()
. Other awaitables in the
aws
sequence
won’t be cancelled
and will continue to run.
若
return_exceptions
is
True
, exceptions are treated the same as successful results, and aggregated in the result list.
若
gather()
is
cancelled
, all submitted awaitables (that have not completed yet) are also
cancelled
.
If any Task or Future from the
aws
sequence is
cancelled
, it is treated as if it raised
CancelledError
– the
gather()
call is
not
cancelled in this case. This is to prevent the cancellation of one submitted Task/Future to cause other Tasks/Futures to be cancelled.
注意
A more modern way to create and run tasks concurrently and wait for their completion is
asyncio.TaskGroup
.
范例:
import asyncio async def factorial(name, number): f = 1 for i in range(2, number + 1): print(f"Task {name}: Compute factorial({number}), currently i={i}...") await asyncio.sleep(1) f *= i print(f"Task {name}: factorial({number}) = {f}") return f async def main(): # Schedule three calls *concurrently*: L = await asyncio.gather( factorial("A", 2), factorial("B", 3), factorial("C", 4), ) print(L) asyncio.run(main()) # Expected output: # # Task A: Compute factorial(2), currently i=2... # Task B: Compute factorial(3), currently i=2... # Task C: Compute factorial(4), currently i=2... # Task A: factorial(2) = 2 # Task B: Compute factorial(3), currently i=3... # Task C: Compute factorial(4), currently i=3... # Task B: factorial(3) = 6 # Task C: Compute factorial(4), currently i=4... # Task C: factorial(4) = 24 # [2, 6, 24]
注意
若
return_exceptions
is False, cancelling gather() after it has been marked done won’t cancel any submitted awaitables. For instance, gather can be marked done after propagating an exception to the caller, therefore, calling
gather.cancel()
after catching an exception (raised by one of the awaitables) from gather won’t cancel any other awaitables.
3.7 版改变: 若 gather itself is cancelled, the cancellation is propagated regardless of return_exceptions .
3.10 版改变: 移除 loop 参数。
从 3.10 版起弃用: Deprecation warning is emitted if no positional arguments are provided or not all positional arguments are Future-like objects and there is no running event loop.
Protect an
awaitable object
from being
cancelled
.
若 aw 是协程,自动作为 Task (任务) 被调度。
语句:
task = asyncio.create_task(something()) res = await shield(task)
相当于:
res = await something()
except
that if the coroutine containing it is cancelled, the Task running in
something()
is not cancelled. From the point of view of
something()
, the cancellation did not happen. Although its caller is still cancelled, so the “await” expression still raises a
CancelledError
.
若
something()
is cancelled by other means (i.e. from within itself) that would also cancel
shield()
.
If it is desired to completely ignore cancellation (not recommended) the
shield()
function should be combined with a try/except clause, as follows:
task = asyncio.create_task(something()) try: res = await shield(task) except CancelledError: res = None
重要
Save a reference to tasks passed to this function, to avoid a task disappearing mid-execution. The event loop only keeps weak references to tasks. A task that isn’t referenced elsewhere may get garbage collected at any time, even before it’s done.
3.10 版改变: 移除 loop 参数。
从 3.10 版起弃用: Deprecation warning is emitted if aw is not Future-like object and there is no running event loop.
An 异步上下文管理器 that can be used to limit the amount of time spent waiting on something.
delay
可以是
None
, or a float/int number of seconds to wait. If
delay
is
None
, no time limit will be applied; this can be useful if the delay is unknown when the context manager is created.
In either case, the context manager can be rescheduled after creation using
Timeout.reschedule()
.
范例:
async def main(): async with asyncio.timeout(10): await long_running_task()
若
long_running_task
takes more than 10 seconds to complete, the context manager will cancel the current task and handle the resulting
asyncio.CancelledError
internally, transforming it into an
asyncio.TimeoutError
which can be caught and handled.
注意
asyncio.timeout()
context manager is what transforms the
asyncio.CancelledError
into an
asyncio.TimeoutError
,这意味着
asyncio.TimeoutError
can only be caught
outside
of the context manager.
Example of catching
asyncio.TimeoutError
:
async def main(): try: async with asyncio.timeout(10): await long_running_task() except TimeoutError: print("The long operation timed out, but we've handled it.") print("This statement will run regardless.")
The context manager produced by
asyncio.timeout()
can be rescheduled to a different deadline and inspected.
Return the current deadline, or
None
if the current deadline is not set.
The deadline is a float, consistent with the time returned by
loop.time()
.
Change the time the timeout will trigger.
若
当
is
None
, any current deadline will be removed, and the context manager will wait indefinitely.
若 当 is a float, it is set as the new deadline.
if 当 is in the past, the timeout will trigger on the next iteration of the event loop.
Return whether the context manager has exceeded its deadline (expired).
范例:
async def main(): try: # We do not know the timeout when starting, so we pass ``None``. async with asyncio.timeout(None) as cm: # We know the timeout now, so we reschedule it. new_deadline = get_running_loop().time() + 10 cm.reschedule(new_deadline) await long_running_task() except TimeoutError: pass if cm.expired: print("Looks like we haven't finished on time.")
Timeout context managers can be safely nested.
3.11 版新增。
类似于
asyncio.timeout()
,除了
当
is the absolute time to stop waiting, or
None
.
范例:
async def main(): loop = get_running_loop() deadline = loop.time() + 20 try: async with asyncio.timeout_at(deadline): await long_running_task() except TimeoutError: print("The long operation timed out, but we've handled it.") print("This statement will run regardless.")
3.11 版新增。
等待 aw awaitable 完成采用超时。
若 aw 是协程,自动作为 Task (任务) 被调度。
timeout
可以是
None
or a float or int number of seconds to wait for. If
timeout
is
None
, block until the future completes.
If a timeout occurs, it cancels the task and raises
TimeoutError
.
要避免任务
cancellation
,将它包裹在
shield()
.
The function will wait until the future is actually cancelled, so the total wait time may exceed the timeout . If an exception happens during cancellation, it is propagated.
If the wait is cancelled, the future aw is also cancelled.
3.10 版改变: 移除 loop 参数。
范例:
async def eternity(): # Sleep for one hour await asyncio.sleep(3600) print('yay!') async def main(): # Wait for at most 1 second try: await asyncio.wait_for(eternity(), timeout=1.0) except TimeoutError: print('timeout!') asyncio.run(main()) # Expected output: # # timeout!
3.7 版改变:
当
aw
is cancelled due to a timeout,
wait_for
waits for
aw
to be cancelled. Previously, it raised
TimeoutError
立即。
3.10 版改变: 移除 loop 参数。
运行
Future
and
Task
instances in the
aws
iterable concurrently and block until the condition specified by
return_when
.
aws iterable must not be empty.
Returns two sets of Tasks/Futures:
(done, pending)
.
用法:
done, pending = await asyncio.wait(aws)
timeout (a float or int), if specified, can be used to control the maximum number of seconds to wait before returning.
Note that this function does not raise
TimeoutError
. Futures or Tasks that aren’t done when the timeout occurs are simply returned in the second set.
return_when indicates when this function should return. It must be one of the following constants:
| 常量 | 描述 |
|---|---|
FIRST_COMPLETED
|
The function will return when any future finishes or is cancelled. |
FIRST_EXCEPTION
|
The function will return when any future finishes by raising an exception. If no future raises an exception then it is equivalent to
ALL_COMPLETED
.
|
ALL_COMPLETED
|
The function will return when all futures finish or are cancelled. |
不像
wait_for()
,
wait()
does not cancel the futures when a timeout occurs.
3.10 版改变: 移除 loop 参数。
3.11 版改变:
将协程对象传递给
wait()
直接是禁止的。
运行 可期待对象 在 aws iterable concurrently. Return an iterator of coroutines. Each coroutine returned can be awaited to get the earliest next result from the iterable of the remaining awaitables.
引发
TimeoutError
if the timeout occurs before all Futures are done.
3.10 版改变: 移除 loop 参数。
范例:
for coro in as_completed(aws): earliest_result = await coro # ...
3.10 版改变: 移除 loop 参数。
从 3.10 版起弃用: Deprecation warning is emitted if not all awaitable objects in the aws iterable are Future-like objects and there is no running event loop.
异步运行函数 func 在单独线程中。
Any *args and **kwargs supplied for this function are directly passed to
func
. Also, the current
contextvars.Context
is propagated, allowing context variables from the event loop thread to be accessed in the separate thread.
Return a coroutine that can be awaited to get the eventual result of func .
This coroutine function is primarily intended to be used for executing IO-bound functions/methods that would otherwise block the event loop if they were run in the main thread. For example:
def blocking_io(): print(f"start blocking_io at {time.strftime('%X')}") # Note that time.sleep() can be replaced with any blocking # IO-bound operation, such as file operations. time.sleep(1) print(f"blocking_io complete at {time.strftime('%X')}") async def main(): print(f"started main at {time.strftime('%X')}") await asyncio.gather( asyncio.to_thread(blocking_io), asyncio.sleep(1)) print(f"finished main at {time.strftime('%X')}") asyncio.run(main()) # Expected output: # # started main at 19:50:53 # start blocking_io at 19:50:53 # blocking_io complete at 19:50:54 # finished main at 19:50:54
直接调用
blocking_io()
in any coroutine would block the event loop for its duration, resulting in an additional 1 second of run time. Instead, by using
asyncio.to_thread()
, we can run it in a separate thread without blocking the event loop.
注意
由于
GIL
,
asyncio.to_thread()
can typically only be used to make IO-bound functions non-blocking. However, for extension modules that release the GIL or alternative Python implementations that don’t have one,
asyncio.to_thread()
can also be used for CPU-bound functions.
3.9 版新增。
将协程提交给给定事件循环。是线程安全的。
返回
concurrent.futures.Future
to wait for the result from another OS thread.
This function is meant to be called from a different OS thread than the one where the event loop is running. Example:
# Create a coroutine coro = asyncio.sleep(1, result=3) # Submit the coroutine to a given loop future = asyncio.run_coroutine_threadsafe(coro, loop) # Wait for the result with an optional timeout argument assert future.result(timeout) == 3
If an exception is raised in the coroutine, the returned Future will be notified. It can also be used to cancel the task in the event loop:
try: result = future.result(timeout) except TimeoutError: print('The coroutine took too long, cancelling the task...') future.cancel() except Exception as exc: print(f'The coroutine raised an exception: {exc!r}') else: print(f'The coroutine returned: {result!r}')
见 并发和多线程 章节的文档编制。
Unlike other asyncio functions this function requires the loop argument to be passed explicitly.
3.5.1 版新增。
返回目前正运行的
Task
实例,或
None
若没有任务在运行。
若
loop
is
None
get_running_loop()
用于获取当前循环。
3.7 版新增。
Return a set of not yet finished
Task
objects run by the loop.
若
loop
is
None
,
get_running_loop()
is used for getting current loop.
3.7 版新增。
A
Future-like
对象运行 Python
协程
。不是线程安全的。
Tasks are used to run coroutines in event loops. If a coroutine awaits on a Future, the Task suspends the execution of the coroutine and waits for the completion of the Future. When the Future is done , the execution of the wrapped coroutine resumes.
Event loops use cooperative scheduling: an event loop runs one Task at a time. While a Task awaits for the completion of a Future, the event loop runs other Tasks, callbacks, or performs IO operations.
Use the high-level
asyncio.create_task()
function to create Tasks, or the low-level
loop.create_task()
or
ensure_future()
functions. Manual instantiation of Tasks is discouraged.
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.
asyncio.Task
继承自
Future
all of its APIs except
Future.set_result()
and
Future.set_exception()
.
Tasks support the
contextvars
module. When a Task is created it copies the current context and later runs its coroutine in the copied context.
3.7 版改变:
添加支持
contextvars
模块。
3.8 版改变: 添加 name 参数。
从 3.10 版起弃用: Deprecation warning is emitted if loop is not specified and there is no running event loop.
返回
True
若 Task
done
.
A Task is done when the wrapped coroutine either returned a value, raised an exception, or the Task was cancelled.
Return the result of the Task.
If the Task is done , the result of the wrapped coroutine is returned (or if the coroutine raised an exception, that exception is re-raised.)
If the Task has been
cancelled
, this method raises a
CancelledError
异常。
If the Task’s result isn’t yet available, this method raises a
InvalidStateError
异常。
Return the exception of the Task.
If the wrapped coroutine raised an exception that exception is returned. If the wrapped coroutine returned normally this method returns
None
.
If the Task has been
cancelled
, this method raises a
CancelledError
异常。
If the Task isn’t
done
yet, this method raises an
InvalidStateError
异常。
Add a callback to be run when the Task is done .
This method should only be used in low-level callback-based code.
见文档编制为
Future.add_done_callback()
了解更多细节。
移除 callback 从回调列表。
This method should only be used in low-level callback-based code.
见文档编制为
Future.remove_done_callback()
了解更多细节。
Return the list of stack frames for this Task.
If the wrapped coroutine is not done, this returns the stack where it is suspended. If the coroutine has completed successfully or was cancelled, this returns an empty list. If the coroutine was terminated by an exception, this returns the list of traceback frames.
The frames are always ordered from oldest to newest.
Only one stack frame is returned for a suspended coroutine.
可选 limit argument sets the maximum number of frames to return; by default all available frames are returned. The ordering of the returned list differs depending on whether a stack or a traceback is returned: the newest frames of a stack are returned, but the oldest frames of a traceback are returned. (This matches the behavior of the traceback module.)
Print the stack or traceback for this Task.
This produces output similar to that of the traceback module for the frames retrieved by
get_stack()
.
limit
自变量会被传递给
get_stack()
直接。
file
argument is an I/O stream to which the output is written; by default output is written to
sys.stderr
.
Return the name of the Task.
If no name has been explicitly assigned to the Task, the default asyncio Task implementation generates a default name during instantiation.
3.8 版新增。
Set the name of the Task.
value argument can be any object, which is then converted to a string.
In the default Task implementation, the name will be visible in the
repr()
output of a task object.
3.8 版新增。
Request the Task to be cancelled.
This arranges for a
CancelledError
exception to be thrown into the wrapped coroutine on the next cycle of the event loop.
The coroutine then has a chance to clean up or even deny the request by suppressing the exception with a
try
… …
except CancelledError
…
finally
block. Therefore, unlike
Future.cancel()
,
Task.cancel()
does not guarantee that the Task will be cancelled, although suppressing cancellation completely is not common and is actively discouraged.
3.9 版改变: 添加 msg 参数。
3.11 版改变:
msg
parameter is propagated from cancelled task to its awaiter.
The following example illustrates how coroutines can intercept the cancellation request:
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()) # Expected output: # # cancel_me(): before sleep # cancel_me(): cancel sleep # cancel_me(): after sleep # main(): cancel_me is cancelled now
返回
True
若 Task
cancelled
.
The Task is
cancelled
when the cancellation was requested with
cancel()
and the wrapped coroutine propagated the
CancelledError
exception thrown into it.
Decrement the count of cancellation requests to this Task.
Returns the remaining number of cancellation requests.
Note that once execution of a cancelled task completed, further calls to
uncancel()
are ineffective.
3.11 版新增。
This method is used by asyncio’s internals and isn’t expected to be used by end-user code. In particular, if a Task gets successfully uncancelled, this allows for elements of structured concurrency like
任务组
and
asyncio.timeout()
to continue running, isolating cancellation to the respective structured block. For example:
async def make_request_with_timeout(): try: async with asyncio.timeout(1): # Structured block affected by the timeout: await make_request() await make_another_request() except TimeoutError: log("There was a timeout") # Outer code not affected by the timeout: await unrelated_code()
While the block with
make_request()
and
make_another_request()
might get cancelled due to the timeout,
unrelated_code()
should continue running even in case of the timeout. This is implemented with
uncancel()
.
TaskGroup
context managers use
uncancel()
in a similar fashion.
Return the number of pending cancellation requests to this Task, i.e., the number of calls to
cancel()
less the number of
uncancel()
调用。
Note that if this number is greater than zero but the Task is still executing,
cancelled()
will still return
False
. This is because this number can be lowered by calling
uncancel()
, which can lead to the task not being cancelled after all if the cancellation requests go down to zero.
This method is used by asyncio’s internals and isn’t expected to be used by end-user code. See
uncancel()
了解更多细节。
3.11 版新增。