yield
不能在async def
函数中用于暂停执行并返回给调用者。在Python 3.5中有不同的方法吗?
修改 Scripted mongo的答案建议使用Python 3.6或将异步生成器定义为类。 Unfortunatley,前者不是一个选择。生成器可以工作,但为此目的定义一个类似乎比我自己的尝试更笨重。
据推测,没有简洁明了的解决方案?
我需要编写可以暂停其操作,返回其调用者并在稍后停止的位置继续执行的函数。这些可以作为状态机实现,可能使用类,这些类会撕掉相关代码并且通常是不可读的。使用生成器,Python提供了一种或多或少的优雅方式来编写这样的函数:
def a():
print('A Part 1')
yield # suspend execution to caller
print('A Part 2')
def run(func):
o = func()
try:
while True:
print('running...')
o.send(None)
except StopIteration:
pass
run(a)
# running...
# A Part 1
# running...
# A Part 2
Python 3.3添加了yield from
语法,它允许很好地嵌套这些函数。 yield from
不是将执行返回给调用者,而是将执行转移到另一个函数:
def b():
print('B Part 1')
yield from a()
print('B Part 2')
run(b)
# running...
# B Part 1
# A Part 1
# running...
# A Part 2
# B Part 2
Python 3.5引入了async def
和await
来区分协同程序和协同程序。当然我宁愿使用这些原生协同程序。只需将b
替换为def
,将async def
替换为yield from
,即可轻松重写await
。但是,我没有找到一个规范的方法来暂停协程并返回给调用者。异步函数中不允许yield
,等待只运行另一个函数。我想出了这个尴尬的解决方案:
import asyncio
@asyncio.coroutine
def awkward_suspend():
yield
async def c():
print('C Part 1')
#yield # SyntaxError: 'yield' inside async function
#await # Syntax Error: invalid syntax
await awkward_suspend()
print('C Part 2')
run(c)
# running...
# C Part 1
# running...
# C Part 2
此方法将yield
包装在普通函数中,从而创建生成器,并将生成器标记为协程,因此可以await
编辑。
这感觉非常像滥用语言。有没有办法在没有asyncio
和尴尬的暂停函数的情况下实现相同的结果?
答案 0 :(得分:1)
您可以改为使用sleep(0):
async def c():
print('C Part 1')
await asyncio.sleep(0)
print('C Part 2')
sleep(0)恰好完成了awkward_suspend-简单的输出 实际上,它们在其中具有该yield语句的私有__sleep0()函数。