Python @asyncio.coroutine与async def
使用我看到的Python @asyncio.coroutine与async def,python,python-3.x,async-await,python-3.5,python-asyncio,Python,Python 3.x,Async Await,Python 3.5,Python Asyncio,使用我看到的asyncio库 @asyncio.coroutine def function(): ... 及 可以互换使用 这两者之间有什么功能上的区别吗?async def是Python 3.5中的一种新语法。 您可以在async defs中使用wait、async with和async for @coroutine是对async def的功能模拟,但它在Python 3.4+中工作,并利用了构造的收益,而不是等待 从实用角度来看,如果您的Python是3.5+,请不要使用@cor
asyncio
库
@asyncio.coroutine
def function():
...
及
可以互换使用
这两者之间有什么功能上的区别吗?async def是Python 3.5中的一种新语法。 您可以在
async def
s中使用wait
、async with
和async for
@coroutine
是对async def
的功能模拟,但它在Python 3.4+中工作,并利用了构造的收益,而不是等待
从实用角度来看,如果您的Python是3.5+,请不要使用@coroutine
。从Python 3.5开始,coroutine
正式成为一种独特的类型,因此异步def
语法以及wait
语句
在此之前,Python3.4通过将常规函数包装到生成器中创建了协同路由,因此使用了decorator语法,而更像生成器的则从中产生 是的,使用async def
语法的本机协同路由与使用asyncio.coroutine
装饰器的基于生成器的协同路由在功能上存在差异
根据,它引入了async def
语法:
本机协同程序对象不实现\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
和
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
方法。因此,它们不能被迭代或传递
到iter()
、list()
、tuple()
和其他内置程序。他们也
不能在<代码>循环中为..使用
试图在本机协同程序上使用\uuuuu iter\uuuu
或\uuuu next\uuuu
对象将导致类型错误
普通生成器不能从
本机协同程序中生成:这样做
将导致类型错误
基于生成器的协同程序(对于异步IO代码,必须使用
@asyncio.coroutine
)可以从
本机coroutine对象中产生
inspect.isgenerator()
和inspect.isgeneratorfunction()
返回本机协同路由对象和本机协同路由函数的False
上面的第1点意味着,虽然使用@asyncio.coroutine
decorator语法定义的协程函数可以像传统的生成器函数一样工作,但使用async def
语法定义的协程函数却不能
下面是两个最小的、表面上等价的协同程序函数,它们由两个语法定义:
import asyncio
@asyncio.coroutine
def decorated(x):
yield from x
async def native(x):
await x
尽管这两个函数的字节码几乎相同:
>>> import dis
>>> dis.dis(decorated)
5 0 LOAD_FAST 0 (x)
3 GET_YIELD_FROM_ITER
4 LOAD_CONST 0 (None)
7 YIELD_FROM
8 POP_TOP
9 LOAD_CONST 0 (None)
12 RETURN_VALUE
>>> dis.dis(native)
8 0 LOAD_FAST 0 (x)
3 GET_AWAITABLE
4 LOAD_CONST 0 (None)
7 YIELD_FROM
8 POP_TOP
9 LOAD_CONST 0 (None)
12 RETURN_VALUE
。。。唯一的区别是GET\u YIELD\u FROM\u ITER
vsGET\u waitiable
,当尝试迭代返回的对象时,它们的行为完全不同:
>>> list(decorated('foo'))
['f', 'o', 'o']
列表(本机('foo'))
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
TypeError:“协同程序”对象不可编辑
显然,'foo'
不是一个可以等待的对象,因此尝试用它调用native()
没有多大意义,但希望重点是它返回的coroutine
对象无论其参数如何都是不可iterable的
Brett Cannon对异步
/等待
语法进行了更详细的研究:更深入地讨论了这一差异。最好了解3.5+中“从不使用@coroutine”的确切原因。这是一个真正的原因还是一个观点/经验法则?例如,我在3.4继承的代码库中有一些@coroutine装饰器,但所有新的开发都在3.5中。我是否应该将这些修饰符转换为async def
?要暂停协同程序执行,必须产生。但是不允许从本机协同程序内部生成yield
!因此,即使在Python3.5+版本中,似乎仍然需要使用@coroutine
。只需使用等待异步。sleep(0)
@hmijail@coroutine
标记的生成器可以等待,但如果可能,最好将它们转换为异步def
。等待异步。sleep(10)
工作得很好。此外,我已经在asyncio master中将asyncio.sleep()
转换为async def
(将作为Python 3.7的一部分发布)。谢谢!但是为什么对本机协程函数执行inspect.iscoroutinefunction()
returnFalse
。
>>> list(decorated('foo'))
['f', 'o', 'o']
>>> list(native('foo'))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'coroutine' object is not iterable