type
status
date
slug
summary
tags
category
icon
password
协程与异步
这里主要使用的就是
asyncio
这个库,用来编写并发代码,使用 async/await 语法,至于协程和异步什么关系,可以参考官方文档的一段话:协程是子例程的更一般形式。子例程可以在某一点进入并在另一点退出。 协程则可以在许多不同的点上进入、退出和恢复。 它们可通过 async def 语句来实现
运行程序
异步程序的运行在不同的 python 版本有不同的方法,如果你在网上看如下这种运行异步程序的方法:
上面写的也是没错的,但此方法是 python3.7 之前运行异步程序的方法,在 3.7 之后有了更简便的写法,如下:
也建议大家使用更高级的写法,因为谁不想少写点代码呢。
基本使用
在 python 中,如果想直接调用一个使用
async
装饰的异步函数,一点要在前面加await
等待运行结束创建任务
当你想创建一个后台任务,让它慢慢执行的时候,可以用这个:
asyncio.create_task(coro, *, name=None)
其中 name 形参是 3.8 加入进去的,意思是任务的名字,使用实例如下:可以看到我们在开始就创建了一个后台任务
task
,该任务会在 3 秒后输出内容,随后又调用了三次函数factorial
,该函数会等待 1 秒后返回,所以输出了以下内容,但如果你们尝试把函数factorial
只运行 1 此或两次,会发现任务task
没有执行完程序就结束了,因为我们只是把它当作一个后台任务来运行,并没有等待,这时有两种方案:- 如果你的程序的服务端程序就不用管了,反正不会结束
- 如果你的代码就是一个脚本可以在最后等待后台任务的结束:
并发运行任务
看了上面你可能会说,我懂了,只要批量创建任务,它不就是并发了吗?也没错,但有更好的方法,就是使用
asyncio.gather(*aws, return_exceptions=False)
,有两个参数,第一个参数就是一堆协程,第二个是发生异常时是直接中断还是随着结果一起返回,默认是中断不返回,这个函数有一个返回值,那就是所有任务的运行结果,如下示例:控制速度
到现在为止,已经完成了使用异步的并发操作,但这种并发是不可控的,比如前文的线程池和进程池,都有一个参数为
max_workers
,是控制速度用的,而在异步编程中也有控制并发速度的,叫做信号量
,简单写一个示例:仔细观看输出的时候你会发现是5个5个一组的输出出来,这就是用到了信号量:
asyncio.Semaphore()
,他只有一个参数就是要限制的并发数量,然后把要限制的代码使用上下文管理器包裹起来就好,但要注意的是,实例化信号量的时候一定要在主事件循环中,也就是使用async
装饰的函数里面才可以,否则会报错,大家可以尝试一下。参考资料
结束了
其实标题上的“并行编程实践并不严谨”,因为线程池和异步的协程都是属于并发的,只有多进程的才是并行。然后呢,本篇文章也只是带大家入个门,知道咋用。至于为啥没写那么详细呢?我更希望看到的各位呢,也只是把它当作一个入门,然后通过自己去了解更深入的知识。
- 作者:昊色居士
- 链接:https://blog.haose.love//article/23be6576-cbb3-4f86-b2bf-e7555418c78b
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。