如何在Python中使用asyncio

Python的异步编程功能 (或简称async)使您可以编写程序,而不必等待独立的任务完成,从而可以完成更多的工作。 Python随附的asyncio库为您提供了使用异步处理磁盘或网络I / O的工具,而无需等待其他所有事情。

asyncio提供了两种用于处理异步操作的API: 高级低级 。 高级API是最常用的API,它们适用于最广泛的应用程序。 低级API功能强大,但也很复杂,并且使用频率较低。

[ 同样在InfoWorld上:Python异步编程入门 ]

在本文中,我们将重点介绍高级API。 在以下各节中,我们将遍历asyncio最常用的高级API,并展示如何将它们用于涉及异步任务的常见操作。

如果您是Python异步的新手,或者可以使用它的工作原理来进行复习, 请先阅读我对Python异步的介绍,然后再深入研究。

在Python中运行协程和任务

自然,异步最常见的asyncio是运行Python脚本的异步部分。 这意味着要学会使用协同程序和任务。

Python的异步组件(包括协程和任务)只能与其他异步组件一起使用,而不能与常规的同步Python一起使用,因此您需要asyncio来弥合差距。 为此,请使用asyncio.run函数:

import asyncio
async def main():
print ("Waiting 5 seconds. ")
for _ in range(5):
await asyncio.sleep(1)
print (".")
print ("Finished waiting.")
asyncio.run(main())

这将运行main() ,以及所有协程main()触发,并等待结果返回。

通常,Python程序应仅具有一个.run()语句,就像Python程序应仅具有一个main()函数一样。 如果不小心使用异步,可能会使程序的控制流难以阅读。 程序的异步代码只有一个入口点,可以防止事情变得繁琐。

异步函数也可以安排为task或包装协程并帮助运行它们的对象。

async def my_task():
do_something()
task = asyncio.create_task(my_task())

然后, my_task()在事件循环中运行,其结果存储在task

如果只有一个任务要从中获取结果,则可以使用asyncio.wait_for(task)等待任务完成,然后使用task.result()检索其结果。 但是,如果您已计划执行许多任务,并且想要等待所有任务完成,请使用asyncio.wait([task1, task2])来收集结果。 (请注意,如果您不希望它们运行超过一定的时间长度,则可以为这些操作设置超时。)

[ 同样在InfoWorld上:6个您不想错过的Python新功能 ]

在Python中管理异步事件循环

asyncio另一个常见用法是管理异步事件循环 。 事件循环是一个运行异步函数和回调的对象。 使用asyncio.run()时会自动创建它。 您通常只希望每个程序仅使用一个异步事件循环,以使事情易于管理。

如果要编写更高级的软件(例如服务器),则需要对事件循环的较低级别的访问。 为此,您可以“揭开面纱”并直接使用事件循环的内部构件 。 但是对于简单的工作,则不需要。

在Python中使用流读取和写入数据

异步的最佳方案是长时间运行的网络操作,在这种情况下,应用程序可能会阻止等待其他资源返回结果。 为此, asyncio提供了stream ,它们是用于执行网络I / O的高级机制。 这包括充当网络请求的服务器。

asyncio使用两个类StreamReaderStreamWriter ,从高层进行网络读写。 如果要从网络读取,则可以使用asyncio.open_connection()打开连接。 该函数返回一个StreamReaderStreamWriter对象的元组,并且您将在每个方法上使用.read().write()方法进行通信。

要从远程主机接收连接,请使用asyncio.start_server()asyncio.start_server()函数将回调函数client_connected_cb作为参数,该回调函数在接收到请求时就会被调用。 该回调函数将StreamReaderStreamWriter实例作为参数,因此您可以处理服务器的读/写逻辑。 ( 有关使用asyncio驱动的aiohttp库的简单HTTP服务器的示例, 请参见此处 。)

[ 不要错过InfoWorld的2020年度技术奖获奖者:年度最佳软件开发,云计算,数据分析和机器学习产品 ]

在Python中同步任务

异步任务倾向于独立运行,但是有时您希望它们彼此通信。 asyncio提供了队列和其他几种在任务之间进行同步的机制:

  • 队列asyncio队列允许异步函数来排队Python对象被其他异步功能消耗-例如,对不同类型的基于它们的行为功能之间分配工作负荷。
  • 同步原语asyncio 锁,事件,条件和信号灯的工作方式与常规Python相对应。

所有这些方法要记住的一件事是它们不是线程安全的。 对于在同一事件循环中运行的异步任务,这不是问题。 但是,如果您尝试与其他事件循环,OS线程或进程中的任务共享信息,则需要使用threading模块及其对象来执行此操作。

此外,如果要跨线程边界启动协程,请使用asyncio.run_coroutine_threadsafe()函数,并将事件循环作为参数传递给它。

在Python中暂停协程

asyncio另一种常见用法以及讨论不足的一种asyncio是在协程内部等待任意任意时间长度。 您不能为此使用time.sleep() ,否则将阻止整个程序。 而是使用asyncio.sleep() ,它允许其他协程继续运行。

[ 通过InfoWorld的App Dev Report新闻通讯了解软件开发中的热门话题 ]

在Python中使用较低级别的异步

最后,如果您认为所构建的应用程序可能需要asyncio的较低级组件,请在开始编码前先看看以下内容:很有可能有人已经构建了一个异步驱动的Python库来满足您的需求。

例如,如果您需要异步DNS查询,请检查aiodns库,对于异步SSH会话,有asyncSSH 。 通过关键字“ async”(以及其他与任务相关的关键字)搜索PyPI,或查看手工编写的Awesome Asyncio列表以获取想法。

翻译自: https://www.infoworld.com/article/3526429/how-to-use-asyncio-in-python.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值