摘要:本文翻译自Coroutines and Tasks,主要介绍asyncio中用于处理协程和任务的方法和接口。在翻译过程当中,译者在官方文档的基础上增长了部分样例代码和示意图表,以帮助读者对文档的理解。本文内容主要针对python3.7,在低版本的python中可能不适用,敬请留意。原创内容,如需转载请注明出处。
译者:马鸣谦(邮箱:1612557569@qq.com)html
协程(coroutines)是经过async/await
定义函数或方法,是使用asyncio进行异步编程的首选途径。以下,是一个协程的例子:python
import asyncio async def main(): print("hello") await asyncio.sleep(1) print("world")
上例中的 main
方法就是咱们定义的协程
。
咱们在交互环境(Python3.7)下执行以上代码,看看效果:shell
>>> import asyncio >>> async def main(): ... print("hello") ... await asyncio.sleep(1) ... print("world") >>> asyncio.run(main()) hello world
须要注意的是:若是像执行普通代码同样直接调用main()
,只会返回一个coroutine
对象,main()
方法内的代码不会执行:编程
>>> main() #直接执行`main()`返回的是一个`coroutine对象`。 <coroutine object main at 0x0000000002C97848>
实际上,asyncio提供了三种执行协程
的机制:安全
asyncio.run()
执行协程。通常用于执行最顶层的入口函数,如main()
。await
一个协程
。通常用于在一个协程
中调用另外一协程
。 以下是一个示例:>>> 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 16:47:10 hello world finished at 16:47:13
执行耗时 3秒bash
asyncio.create_task()
方法将Coroutine(协程)
封装为Task(任务)
。通常用于实现异步并发操做。 须要注意的是,只有在当前线程存在事件循环的时候才能建立任务(Task)。咱们修改以上的例程,并发执行 两个say_after
协程。多线程
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')}") await task1 await task2 print(f"finished at {time.strftime('%X')}")
执行asyncio.run(main())
,结果以下:并发
started at 17:01:34 hello world finished at 17:01:36
耗时2秒less
若是一个对象可以被用在await
表达式中,那么咱们称这个对象是可等待对象(awaitable object)
。不少asyncio API
都被设计成了可等待的
。
主要有三类可等待对象:异步
coroutine
Task
Future
。Python的协程
是可等待的(awaitable)
,所以可以被其余协程
用在await
表达式中。
import asyncio async def nested(): print("something") async def main(): # 若是直接调用 "nested()",什么都不会发生. # 直接调用的时候只是建立了一个 协程对象 ,但这个对象没有被 await, # 因此它并不会执行. nested() # 那么咱们 await 这个协程,看看会是什么结果: await nested() # 将会打印 "something". asyncio.run(main())
重要:在这篇文章中,术语coroutine
或协程
指代两个关系紧密的概念:
协程函数(coroutine function)
:由async def
定义的函数;协程对象(coroutine object)
:调用 协程函数
返回的对象。asyncio也支持传统的基于生成器的协程。
Task
用来 并发的 调度协程。
当一个协程
经过相似 asyncio.create_task()
的函数被封装进一个 Task
时,这个协程
会很快被自动调度执行:
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())
Future
是一种特殊的 底层 可等待对象,表明一个异步操做的最终结果。
当一个Future
对象被await
的时候,表示当前的协程会持续等待,直到 Future
对象所指向的异步操做执行完毕。
在asyncio中,Future
对象能使基于回调的代码被用于asyn/await
表达式中。
通常状况下,在应用层编程中,没有必要 建立Future
对象。
有时候,有些Future
对象会被一些库和asyncio API暴露出来,咱们能够await
它们:
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() )
底层函数返回Future
对象的一个例子是:loop.run_in_executor
asyncio.run(coro, * , debug=False)
这个函数运行coro
参数指定的 协程
,负责 管理asyncio事件循环 , 终止异步生成器。
在同一个线程中,当已经有asyncio事件循环在执行时,不能调用此函数。
若是debug=True
,事件循环将运行在 调试模式。
此函数老是建立一个新的事件循环,并在最后关闭它。建议将它用做asyncio程序的主入口,而且只调用一次。
Python3.7新增
重要:这个函数是在Python3.7被临时添加到asyncio中的。
asyncio.create_task(coro)
将coro
参数指定的协程(coroutine)
封装到一个Task
中,并调度执行。返回值是一个Task
对象。
任务在由get_running_loop()
返回的事件循环(loop)中执行。若是当前线程中没有正在运行的事件循环,将会引起RuntimeError
异常:
import asyncio async def coro_1(): print("do somthing") task = asyncio.create_task(coro_1())
由于当前线程中没有正运行的事件循环,因此引起异常:
Traceback (most recent call last): File "C:\Program Files\Python37\lib\site-packages\IPython\core\interactiveshell.py", line 3265, in run_code exec(code_obj, self.user_global_ns, self.user_ns) File "<ipython-input-4-456c15a4ed16>", line 1, in <module> task = asyncio.create_task(coro_1()) File "C:\Program Files\Python37\lib\asyncio\tasks.py", line 324, in create_task loop = events.get_running_loop() RuntimeError: no running event loop
对以上代码稍做修改,建立main()
方法,在其中建立Task
对象,而后在主程序中利用asyncio.run()
建立事件循环
:
import asyncio async def coro(): print("something is running") async def main(): task = asyncio.create_task(coro()) print(asyncio.get_running_loop()) asyncio.run(main())
执行结果以下:
<_WindowsSelectorEventLoop running=True closed=False debug=False> something is running
此函数已经被引入到Python3.7。在Python早期版本中,可使用底层函数asyncio.ensure_future()
代替。
async def coro(): ... # In Python 3.7+ task = asyncio.create_task(coro()) ... # This works in all Python versions but is less readable task = asyncio.ensure_future(coro()) ...
Python3.7新增
coroutine asyncio.sleep(delay,result=None,* ,loop=None)
阻塞delay
秒,例如delay=3
,则阻塞3秒。
若是指定了result
参数的值
,则在协程结束时,将该值
返回给调用者。
sleep()
一般只暂停当前task
,并不影响其余task
的执行。
不建议使用loop
参数,由于Python计划在3.10
版本中移除它。
如下是一个协程的例子,功能是在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())
执行结果大体以下:
2018-11-20 11:27:15.961830 2018-11-20 11:27:16.961887 2018-11-20 11:27:17.961944 2018-11-20 11:27:18.962001 2018-11-20 11:27:19.962059 2018-11-20 11:27:20.962116
awaitable asyncio.gather(* aws, loop=None, return_exceptions=False)
并发执行aws
参数指定的 可等待(awaitable)对象
序列。
若是 aws
序列中的某个 awaitable 对象
是一个 协程
,则自动将这个 协程
封装为 Task
对象进行处理。例如:
import asyncio async def factorial(name, number): f = 1 for i in range(2, number + 1): print(f"Task {name}: Compute factorial({i})...") await asyncio.sleep(1) f *= i print(f"Task {name}: factorial({number}) = {f}") async def main(): # Schedule three calls *concurrently*: await asyncio.gather( factorial("A", 2), factorial("B", 3), factorial("C", 4), ) asyncio.run(main()) # Expected output: # # Task A: Compute factorial(2)... # Task B: Compute factorial(2)... # Task C: Compute factorial(2)... # Task A: factorial(2) = 2 # Task B: Compute factorial(3)... # Task C: Compute factorial(3)... # Task B: factorial(3) = 6 # Task C: Compute factorial(4)... # Task C: factorial(4) = 24
若是全部的awaitable
对象都执行完毕,则返回 awaitable对象执行结果的聚合列表。返回值的顺序于aws
参数的顺序一致。
简单修改以上代码:
import asyncio async def factorial(name, number): f = 1 for i in range(2, number + 1): #print(f"Task {name}: Compute factorial({i})...") await asyncio.sleep(1) f *= i #print(f"Task {name}: factorial({number}) = {f}") return number async def main(): # Schedule three calls *concurrently*: print(await asyncio.gather( factorial("A", 2), factorial("B", 3), factorial("C", 4), )) asyncio.run(main()) # Expected output: # #[2, 3, 4]#await asyncio.gather()的返回值是一个列表, #分别对应factorial("A", 2),factorial("B", 3),factorial("C", 4)的执行结果。
若是return_execptions
参数为False
(默认值即为False
),引起的第一个异常会当即传播给等待gather()
的任务,即调用await asyncio.gather()
对象。序列中其余awaitable
对象的执行不会受影响。例如:
import asyncio async def division(divisor, dividend): if divisor == 0: raise ZeroDivisionError else: print(f"{dividend}/{divisor}={dividend/divisor}") return dividend/divisor async def main(): # Schedule three calls *concurrently*: print(await asyncio.gather( division(0, 2), division(1, 2), division(2, 2), )) asyncio.run(main())
执行结果:
2/1=2.0 2/2=1.0 Traceback (most recent call last): File "test.py", line 19, in <module> asyncio.run(main()) File "c:\Program Files\Python37\lib\asyncio\runners.py", line 43, in run return loop.run_until_complete(main) File "c:\Program Files\Python37\lib\asyncio\base_events.py", line 573, in run_until_complete return future.result() File "test.py", line 16, in main division(2, 2), File "test.py", line 6, in division raise ZeroDivisionError ZeroDivisionError
若是return_exceptions
参数为True
,异常会和正常结果同样,被聚合到结果列表中返回。
对以上代码稍做修改,将return_exceptions
设为True
:
import asyncio async def division(divisor, dividend): if divisor == 0: raise ZeroDivisionError else: print(f"{dividend}/{divisor}={dividend/divisor}") return dividend/divisor async def main(): # Schedule three calls *concurrently*: print(await asyncio.gather( division(0, 2), division(1, 2), division(2, 2), return_exceptions=True )) asyncio.run(main())
执行结果以下:
2/1=2.0 2/2=1.0 [ZeroDivisionError(), 2.0, 1.0]#错误不会向上传播,而是做为结果返回
若是gather()
被取消,则提交的全部awaitable
对象(还没有执行完成的)都会被取消。例如:
import asyncio async def division(divisor, dividend): if divisor == 0: raise ZeroDivisionError else: await asyncio.sleep(divisor) print(f"{dividend}/{divisor}={dividend/divisor}") return dividend/divisor async def main(): # Schedule three calls *concurrently*: t = asyncio.gather( division(0, 2), division(1, 5), division(3, 6), return_exceptions=True ) await asyncio.sleep(2) t.cancel() await t asyncio.run(main())
执行结果:
5/1=5.0 #除已执行的以外,其余的任务所有被取消 Traceback (most recent call last): File "test.py", line 23, in <module> asyncio.run(main()) File "c:\Program Files\Python37\lib\asyncio\runners.py", line 43, in run return loop.run_until_complete(main) File "c:\Program Files\Python37\lib\asyncio\base_events.py", line 573, in run_until_complete return future.result() concurrent.futures._base.CancelledError #在return_exceptions=True的状况下,异常依然向上传播。
若是aws
中某些Task
或Future
被取消,gather()
调用不会被取消,被取消的Task
或Future
会以引起CancelledError
的方式被处理。这样能够避免个别awaitable
对象的取消操做影响其余awaitable
对象的执行。
例如:
import asyncio async def division(divisor, dividend): if divisor == 0: raise ZeroDivisionError else: await asyncio.sleep(divisor) print(f"{dividend}/{divisor}={dividend/divisor}") return dividend/divisor async def main(): # Schedule three calls *concurrently*: task1 = asyncio.create_task(division(0, 2)) task2 = asyncio.create_task(division(1, 5)) task3 = asyncio.create_task(division(3, 6)) t = asyncio.gather( task1, task2, task3, return_exceptions=True ) task1.cancel() print(await t) asyncio.run(main())
预期执行结果以下:
5/1=5.0 6/3=2.0 [CancelledError(), 5.0, 2.0] # 仅task1被取消,其余任务不受影响。
awaitable asyncio.shield(aw, * , loop=None)
防止awaitable
对象被取消(cancelled)执行。
若是aw
参数是一个协程(coroutines)
,该对象会被自动封装为Task
对象进行处理。
一般,代码:
#code 1 res = await shield(something())
同代码:
#code 2 res = await something()
是等价的。
特殊状况是,若是包含以上代码的协程
被 取消,code 1
与code 2
的执行效果就彻底不一样了:
code 1
中,运行于something()
中的任务 不会被取消。code 2
中,运行于something()
中的任务 会被取消。在code 1
中,从something()
的视角看,取消操做并无发生。然而,事实上它的调用者确实被取消了,因此await shield(something())
仍然会引起一个CancelledError
异常。
import asyncio import time async def division(divisor, dividend): if divisor == 0: raise ZeroDivisionError else: await asyncio.sleep(divisor) print(f"{time.strftime('%X')}:{dividend}/{divisor}={dividend/divisor}") return dividend/divisor async def main(): # Schedule three calls *concurrently*: print(f"Start time:{time.strftime('%X')}") task1 = asyncio.shield(division(1, 2)) task2 = asyncio.create_task(division(1, 5)) task3 = asyncio.create_task(division(3, 6)) res = asyncio.gather(task1, task2, task3, return_exceptions=True) task1.cancel() task2.cancel() print(await res) asyncio.run(main())
执行结果:
Start time:10:38:48 10:38:49:2/1=2.0 10:38:51:6/3=2.0 [CancelledError(), CancelledError(), 2.0] #task1虽然被取消,可是division(1,2)依然正常执行了。 #task2被取消后,division(1,5)没有执行 #虽然task1内的协程被执行,但返回值依然为CancelledError
若是something()
以其余的方式被取消,好比从自身内部取消,那么shield()
也会被取消。
若是但愿彻底忽略取消操做
(不推荐这么作),则能够将shield()
与try/except
结合起来使用:
try: res = await shield(something()) except CancelledError: res = None
coroutine asyncio.wait_for(aw,timeout,*,loop=None)
在timeout
时间以内,等待aw
参数指定的awaitable
对象执行完毕。
若是aw
是一个协程,则会被自动做为Task
处理。
timeout
能够是None
也能够是一个float
或int
类型的数字,表示须要等待的秒数。若是timeout
是None
,则永不超时,一直阻塞到aw
执行完毕。
若是达到timeout
时间,将会取消待执行的任务,引起asyncio.TimeoutError
.
若是想避免任务被取消,能够将其封装在shield()
中。
程序会等待到任务确实被取消掉,因此等待的总时间会比timeout
略大。
若是await_for()
被取消,aw
也会被取消。
loop
参数将在Python3.10中删除,因此不推荐使用。
示例:
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 asyncio.TimeoutError: print('timeout!') asyncio.run(main()) # Expected output: # # timeout!
Python3.7新特性:当aw
由于超时被取消,wait_for()
等到aw
确实被取消以后返回异常。在之前的版本中,wait_for
会当即返回异常。
coroutine asyncio.wait(aws,*,loop=None,timeout=None,return_when=ALL_COMPLETED)
并发执行aws
中的awaitable
对象,一直阻塞到return_when
指定的状况出现。
若是aws
中的某些对象是协程(coroutine)
,则自动转换为Task
对象进行处理。直接将coroutine
对象传递给wait()
会致使使人迷惑的执行结果,因此不建议这么作。
返回值是两个Task/Future
集合:(done,pending
)。
用法示例:
done,pending = await asyncio.wait(aws)
loop
参数将在Python3.10中删除,因此不建议使用。
timeout
参数能够是一个int
或float
类型的值,能够控制最大等待时间。
须要注意的是,wait()
不会引起asyncio.TimeoutError
错误。返回前没有被执行的Future
和Task
会被简单的放入pending
集合。
return_when
决定函数返回的时机。它只能被设置为如下常量:
|Constant|Description|
|-|-|
|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()
不会再超时的时候取消任务。
注意:
由于wait()
会自动将协程
转换为Task对象
进行处理,而后返回这些隐式建立的Task
到(done,pending)集合,因此如下代码不会如预期的那样执行。
async def foo(): return 42 coro = foo() done, pending = await asyncio.wait({coro}) if coro in done: # 由于wait()会自动将协程转换为Task对象进行处理,而后返回这些隐式建立的Task到(done,pending)集合,因此这个条件分支永远不会被执行。
上面的代码能够作以下修正:
async def foo(): return 42 task = asyncio.create_task(foo()) done, pending = await asyncio.wait({task}) if task in done: # 这回能够正常执行了.
因此,正如上文所讲,不建议将coroutine
对象直接传递给wait()
。
asyncio.as_completed(aws,*,loop=None,timeout=None)
并发执行aws
中的awaitable
对象。返回一个Future
对象迭代器。每次迭代时返回的Future
对象表明待执行的awaitable
对象集合里最先出现的结果。注意:迭代器返回的顺序与aws
列表的顺序无关,只与结果出现的迟早有关。
若是超时以前还有Future
对象未完成,则引起asyncio.TimeoutError
异常。
用法示例:
for f in as_completed(aws): earliest_result = await f # ...
如下为一个完整的例子:
import asyncio import time async def eternity(delay): await asyncio.sleep(delay) print(f"delay for {delay} seconds.") return delay async def main(): print(f"Start at: {time.strftime('%X')}") tasks = [eternity(i) for i in range(10)] for f in asyncio.as_completed(tasks): res = await f print(f"End at: {time.strftime('%X')}") asyncio.run(main())
执行结果以下:
Start at: 17:19:11 delay for 0 seconds. delay for 1 seconds. delay for 2 seconds. delay for 3 seconds. delay for 4 seconds. delay for 5 seconds. delay for 6 seconds. delay for 7 seconds. delay for 8 seconds. delay for 9 seconds. End at: 17:19:20
asyncio.run_coroutine_threadsafe(coro,loop)
向loop
指定的事件循环提交一个由coro
指定协程。线程安全。
返回一个concurrent.futures.Future
对象,等待另外一个线程返回结果。
这个函数用于从当前线程
向运行事件循环的线程
提交协程(coroutine)
。
例如:
# 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
若是协程
出现异常,返回的Future
会收到通知。返回的Future
也能够被用做取消事件循环中的任务:
try: result = future.result(timeout) except asyncio.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}')
能够参考并发与多线程章节。
与其余asyncio函数不一样,该函数须要 显式 传递loop
参数。
新增于Python 3.5.1
asyncio.current_task(loop=None)
返回事件循环中正在运行的Task
实例,若是没有Task
在执行,则返回None
。
若是loop
为None
,则使用get_running_loop()
获取当前事件循环。
新增于Python3.7
asyncio.all_tasks(loop=None)
返回事件循环中还没有运行结束的Task
对象集合。
若是loop
为None
,则,使用get_running_loop()
获取当前事件循环。
新增于Python3.7
class asyncio.Task(coro,*,loop=None)
相似与Future
对象,用于执行Python协程。非线程安全。
Tasks
用于在事件循环
中执行协程
。若是协程
等待一个Future
,那么Task
会暂停协程
的执行,直到Future
执行完成。当Future
完成时,协程
的执行会恢复。
事件循环的 协做调度 模式:一个事件循环同一时间只执行一个Task
。当这个Task
等待某个Future
返回时,事件循环执行其余的Task
、回调
或IO操做
。
能够经过高层函数asyncio.create_task()
建立Task
,或者经过底层函数loop.create_task()
和ensure_future()
建立Task
。可是不建议直接实例化Task
对象。
若是想要取消一个Task
的执行,可使用cancel()
方法。调用cancel()
会引发Task
对象向被封装的协程
抛出CancelledError
异常。当取消行为发生时,若是协程
正在等待某个Future
对象执行,该Future
对象将被取消。
cancelled()
方法用于检查某个Task
是否已被取消。若是Task
封装的协程
没有阻止CancelledError
异常,且Task
确实被取消了,则该方法返回True
。
asyncio.Task
继承了Future
类中除Future.set_result()
和Future.set_exception()
之外的全部方法。
Task
对象支持contextvars
模块:当一个Task
被建立的时候,它会复制当前的上下文,而后在复制的上下文副本中执行协程。
Python3.7中的变动:添加了对contextvars
模块的支持。
申请取消任务。
将在下一个事件循环周期中将CancelledError
异常抛给封装在Task
中的协程。
收到CancelledError
异常后,协程
有机会处理异常,甚至以try ...except CancelledError ...finally
来拒绝请求。所以,与Future.cancel()
不一样,Task.cancel()
不能保证Task
必定被取消掉。固然,拒绝取消请求这种操做并不常见,并且很不提倡。
如下例子能够说明协程如何拦截取消请求:
import asyncio 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
若是Task
已经被取消,则返回True
。
当取消请求经过cancel()
被提交,且Task
封装的协程
传播了抛给它的CancelledError
异常,则此Task
被取消。
若是Task
已完成,则返回True
。
Task
完成有三种状况:
Task
被取消返回Task
的执行结果。
若是Task
已经完成,则返回Task
封装的协程的执行结果(若是Task
封装的协程引起异常,则从新引起该异常)。
若是Task
已经取消,则该方法引起CancelledError
异常。
若是Task
的结果还不可用,该方法引起InvalidStateError
异常。
返回Task
的异常。
若是封装的协程引起了异常,则返回此异常。若是封装的协程执行正常,则返回None
。
若是Task
已被取消,则引起CancelledError
异常。
若是Task
还没有完成,则引起InvalidStateError
异常。
添加一个回调函数,在Task
完成后执行。
这个方法只应用在基于回调的底层编程中。
具体细节能够参考Future.remove_done_callback()
返回此Task
的堆栈帧列表。
帧的顺序老是 由旧到新。
暂停中的协程只返回一个堆栈帧。
可选参数limit
用于限定返回帧的最大数目。默认状况下,全部有效的帧都会返回。
在返回堆栈和返回异常回溯时,列表的顺序会有所不一样:
打印Task
的栈帧或异常回溯。
此方法用于输出由get_stack()
取回的帧列表,输出形式相似于回溯(traceback)模块
limit
参数会直接传递给get_stack()
。
file
参数指定输出的I/O流,默认为sys.stderr
。
返回一个事件循环上全部任务的集合。
默认状况下,当前事件循环上全部的任务都会被返回。若是loop
参数为'None',则经过get_event_loop()
方法获取当前事件循环。
此方法将在Python3.9中被移除,因此不建议使用。可使用asyncio.all_tasks()
代替。
返回当前正在运行的Task
或None
。
若是loop
参数为'None',则经过get_event_loop()
方法获取当前事件循环。
此方法将在Python3.9中被移除,因此不建议使用。可使用asyncio.current_task()
代替。
提示:对基于生成器的协程的支持将在Python3.10中移除,不建议使用。
基于生成器的协程是早期的异步实现方式,出如今async/await
语法以前,使用yield from
表达式等待Future
或其余协程。
基于生成器的协程应该用@asyncio.coroutine
来修饰,尽管这不是强制的。
基于生成器的协程的修饰器。
这个修饰器能使传统的基于生成器的协程
与async/await
语法兼容:
@asyncio.coroutine def old_style_coroutine(): yield from asyncio.sleep(1) async def main(): await old_style_coroutine()
此修饰器将在Python3.10中被移除,因此不建议再使用。
此修饰器不能用于async def
的协程中。
若是obj
对象是一个coroutine
对象,则返回True
。
此方法与inspect.iscoroutine()
不一样,由于它对基于生成器的协程也返回True
。
若是func
是一个coroutine
方法,则返回True
。
此方法inspect.iscoroutinefunction()
不一样,由于它对用@coroutine
修饰的基于生成器的协程也返回True
。