asyncio异步IO--协程(Coroutine)与任务(Task)详解 (2)

这个函数运行coro参数指定的 协程,负责 管理asyncio事件循环终止异步生成器
在同一个线程中,当已经有asyncio事件循环在执行时,不能调用此函数。
如果debug=True,事件循环将运行在 调试模式
此函数总是创建一个新的事件循环,并在最后关闭它。建议将它用作asyncio程序的主入口,并且只调用一次。
Python3.7新增
重要:这个函数是在Python3.7被临时添加到asyncio中的。

创建Task asyncio.create_task(coro)

将coro参数指定的协程(coroutine)封装到一个Task中,并调度执行。返回值是一个Task对象。
任务在由返回的事件循环(loop)中执行。如果当前线程中没有正在运行的事件循环,将会引发异常:

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新增

Sleeping 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 并发执行Tasks 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)的执行结果。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyzspx.html