并发编程要求用户理解任务映射到线程/进程,并使用threading或其他包在程序中重现这个过程。

asyncio只需要用户理解async定义的函数可并发执行到await定义的位置,极大简化了并发编程。

1 async和await

普通函数前面加 async 关键字,标志该函数可以并发执行

await 表示等待async 定义函数执行到当前位置,然后再往下执行。类似于并发程序中的barrier。

await 只能在带有 async 定义的函数中运行。

asynico.run() 启动async定义可并发运行的函数。

2 asyncio并发示例

这里示例代码来自网络。

示例1: 直接启动

import asyncio
import time

async def visit_url(url, response_time):
    """访问 url"""
    await asyncio.sleep(response_time)
    return f"访问{url}, 已得到返回结果"

start_time = time.perf_counter()
task = visit_url('http://wangzhen.com', 2)
asyncio.run(task)
print(f"消耗时间:{time.perf_counter() - start_time}")

python单独运行ok,在jupyter运行会报错,原因及方案参考附录问题1。

示例2:  事件循环中启动

aysncio.get_event_loop().create_task()将task添加到已有事件循环中,解决jupyter报错问题。

import asyncio
import time
 
async def visit_url(url, response_time):
    """访问 url"""
    await asyncio.sleep(response_time)
    print("visit_url done")
    return f"访问{url}, 已得到返回结果"

task = visit_url('http://wangzhen.com', 2)
asyncio.get_event_loop().create_task(task)

示例3: async函数和一般函数

jupyter环境需要采用get_event_loop的方式运行

import asyncio
import time

async def my_coroutine():
    time.sleep(3)
    print("Coroutine")

async def main():
    await my_coroutine()
    print("main ok")

asyncio.run(main()) # for pure run
# asyncio.get_event_loop().create_task(main()) # for jupyter
print("done")

附录

问题1 jupyter运行提示事件循环报错

RuntimeError: asyncio.run() cannot be called from a running event loop

原因: 

Jupyter Notebook每个cell是一个独立事件循环。在cell中调用asyncio.run()时,其实就是在创建一个新的事件循环,并且要将其设置为运行状态。由于已经有一个cell独立事件循环在运行,所以就会报错。

解决方案: 

aysncio.get_event_loop().create_task()将task添加到已有的事件循环中,示例如下。

asyncio.get_event_loop().create_task(asyncio.wait(task))

reference

---

python教程:使用 async 和 await 协程进行并发编程

https://www.cnblogs.com/heniu/p/12740400.html

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐