我一直试图理解异步编程,尤其是在Python中。我知道asyncio是基于事件循环构建的,该事件循环调度了协程的执行,但是我已经阅读了定义协程的几种不同方式,并且我对它们之间如何相互关联感到困惑。
我阅读了this article,以获取有关该主题的更多背景信息。尽管它涵盖了我提到的四种协程中的每一种,但并未完全描述它们之间的区别。没有任何外部模块,就可以使用yield
作为等号右边的表达式来创建协程,然后可以通过.send()
输入数据。但是,使用@asyncio.coroutine
和@types.coroutine
装饰器的代码示例从未使用过我发现的.send()
。本文中的代码示例如下:
# Coroutine using yield as an expression
def coro():
hello = yield "Hello"
yield hello
c = coro()
print(next(c), end=" ")
print(c.send("World")) # Outputs Hello World
# Asyncio generator-based coroutine
@asyncio.coroutine
def display_date(num, loop):
end_time = loop.time() + 50.0
while True:
print("Loop: {} Time: {}".format(num, datetime.datetime.now()))
if (loop.time() + 1.0) >= end_time:
break
yield from asyncio.sleep(random.randint(0, 5))
# Types generator-based coroutine
@types.coroutine
def my_sleep_func():
yield from asyncio.sleep(random.randint(0, 5))
# Native coroutine in Python 3.5+
async def display_date(num, loop, ):
end_time = loop.time() + 50.0
while True:
print("Loop: {} Time: {}".format(num, datetime.datetime.now()))
if (loop.time() + 1.0) >= end_time:
break
await asyncio.sleep(random.randint(0, 5))
我的问题是:
yield
协程与types
或asyncio
装饰的协程如何相关?.send()
功能在哪里使用?@asyncio.coroutine
和@types.coroutine
装饰符有何区别?我读过this answer试图理解这一点,但是这里提到的唯一区别是,types
协程如果没有yield语句,则执行起来就像子例程。还有什么吗?async/await
协程在功能和实现上有何不同?答案 0 :(得分:0)
您可能会笑,我看了一下https://www-01.ibm.com/support/docview.wss?uid=swg27011920,发现它使用了types.coroutine
(我添加了任何带有#!>
的评论)< / p>
def coroutine(func):
"""Decorator to mark coroutines...."""
#!> so clearly the async def is preferred.
warnings.warn('"@coroutine" decorator is deprecated since Python 3.8, use "async def" instead',
DeprecationWarning,
stacklevel=2)
if inspect.iscoroutinefunction(func):
#!> since 3.5 clearly this is returning something functionally identical to async def.
# In Python 3.5 that's all we need to do for coroutines
# defined with "async def".
return func
if inspect.isgeneratorfunction(func):
coro = func
else:
#!> omitted, makes a wrapper around a non generator function.
#!> USES types.coroutine !!!!
coro = types.coroutine(coro)
if not _DEBUG:
wrapper = coro
else:
#!> omitted, another wrapper for better error logging.
wrapper._is_coroutine = _is_coroutine # For iscoroutinefunction().
return wrapper
因此,我认为这仅归结于历史性内容,asyncio
的存在时间比types
更长,因此在此完成了原始处理,然后当类型出现时,将真正的包装器移到那里,并且异步继续只是有一些额外的包装材料。但归根结底,两者都只是模仿async def