最近在看协程这个话题,完全处于好奇,简单了解了下Python中的表示形式,这里仅仅是对Python中的协程很浅很浅的了解。
一、Python中的协程背景
0、Python3.4之前官方不支持协程(第三方的库支持gevent、Tornado)。
1、3.4版本内置了异步I/O库asyncio, 通过装饰器@asyncio.coroutine和yield from表达式实现协程。
2、3.5版本开始引入async/await语法,用来简化协程的使用并且便于理解,实际是3.4版本实现协程的语法糖。
3、3.7版本增加了asyncio.run()方法,更方便的实现协程。
二、Python3.5+协程原理
0、async语法及协程函数
使用 async def 语法定义的函数总是为协程函数,即使它们不包含 await 或 async 关键字。
1、await语法
挂起协程的执行以等待一个可等待对象(awaitable), 比如协程、任务、Future。
2、asyncio.create_task()函数用了并发执行多个协程任务。
三、Python3.7+协程应用
关于Python不同版本协程的实现,参考[掘金:理解Python的协程(Coroutine)]。这里主要整理3.7+中的应用。
以下示例来自Python官网, 协程与任务。
0、执行一个协程序
import asyncio async def main(): print('hello') await asyncio.sleep(1) print('python') asyncio.run(main())
以上代码保存文件test1.py, 并执行, 先打印’hello’, 隔1s打印’python’
python3 test1.py hello python
1、等待一个协程
import asyncio 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, 'python') print(f"finished at {time.strftime('%X')}") asyncio.run(main())
以上代码保存文件test2.py, 并执行, 等待1s打印’hello’, 隔2s打印’python’, 开始和结束之间用了3s
python3 test2.py started at 21:53:47 hello world finished at 21:53:50
2、多协程并发执行
import asyncio import time async def say_after(delay, what): await asyncio.sleep(delay) print(what) async def main(): task1 = asyncio.create_task( say_after(1, 'hello')) task2 = asyncio.create_task( say_after(2, 'python')) print(f"started at {time.strftime('%X')}") # Wait until both tasks are completed (should take # around 2 seconds.) await task1 await task2 print(f"finished at {time.strftime('%X')}") asyncio.run(main())
以上代码保存文件test3.py, 并执行, 等待1s打印’hello’, 隔1s打印’python’, 开始和结束之间用了2s
python3 test3.py started at 21:58:56 hello python finished at 21:58:58
四、问题
0、在运行代码test1.py的时候,提示AttributeError: partially initialized module ‘asyncio’ has no attribute ‘run’ (most likely due to a circular import)。
原因:文件名一开始命名为asyncio.py, 所以出现了循环import。
类似的问题,如果用低于3.7版本来执行,也是提示,参考stackoverflow:Python3.6 AttributeError: module ‘asyncio’ has no attribute ‘run’
五、总结
0、Python中内置了协程的功能,实现多协程很方便,比PHP简洁太多,不过没有Lua中协程易于理解。
1、Python不同版本差异真的很大。
2、Python的交互式运行环境可以写多行代码,PHP只能写一行。
python3 Python 3.8.3 (default, May 17 2020, 17:00:38) [GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import asyncio >>> async def main(): ... print('hello') ... print('python') ... >>> asyncio.run(main()) hello python
PHP回车换行就相当于执行了
php -a Interactive shell php > class Solution() {} PHP Parse error: syntax error, unexpected '(', expecting '{' in php shell code on line 1 php >