Python 3.5中能否省略async def关键字仍实现异步功能?
关于Python 3.5中省略
async def实现异步运行的问题 好问题!在Python 3.5里,你没法直接省略async def关键字还让代码真正实现异步运行——因为async def是定义协程函数的核心标识,Python解释器正是靠它来识别这是一个可以被异步调度的特殊函数。
先说说你示例代码里的问题
你的代码里loop.await(sleep)是错误的:
- 事件循环对象并没有
await这个方法; sleep是协程函数,你需要调用它得到协程对象(比如sleep())才能交给事件循环处理。
为什么不能省略async def?
Python 3.5引入了async/await语法,这是官方推荐的异步编程标准:
- 用
async def定义的函数,调用后不会立即执行函数体,而是返回一个协程对象; - 这个协程对象需要交给事件循环(比如
asyncio.get_event_loop())来调度执行,才能实现异步等待的效果; - 如果用普通的
def定义函数,调用后会直接同步执行函数体里的所有代码,哪怕你把它放到事件循环里,也只是同步运行,完全达不到异步的目的。
正确的写法示例
如果你想在普通函数里调用异步代码,应该这样写:
import asyncio async def sleep(): await asyncio.sleep(1) print("异步睡眠完成") def mysleep(): loop = asyncio.get_event_loop() # 调用协程函数得到协程对象,再让事件循环运行它 loop.run_until_complete(sleep()) def main(): mysleep() if __name__ == "__main__": main()
有没有不用async def的替代方案?
Python 3.5之前,异步编程是用生成器模拟协程的,你可以用@asyncio.coroutine装饰普通生成器函数,搭配yield from来实现类似效果:
import asyncio @asyncio.coroutine def sleep(): yield from asyncio.sleep(1) print("基于生成器的异步睡眠完成") def mysleep(): loop = asyncio.get_event_loop() loop.run_until_complete(sleep()) def main(): mysleep() if __name__ == "__main__": main()
不过要注意,这种方式在Python 3.5只是为了兼容旧代码,官方已经不推荐使用了,而且在Python 3.10及以后版本中已经被移除,所以还是老老实实用async def更稳妥。
总结
在Python 3.5中,没有async def(或旧的@asyncio.coroutine装饰器),你无法定义能被异步调度的协程,普通函数只能同步执行。如果想要代码异步运行,async def是必不可少的。
内容的提问来源于stack exchange,提问作者speller
相关产品推荐
相关产品推荐

