所以经过一番挖掘,我想我找到了全局执行协程的最简单解决方案。
如果你>>> dir(coro)Python 会打印出以下属性:
['__await__', '__class__', '__del__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'close', 'cr_await', 'cr_code', 'cr_frame', 'cr_origin', 'cr_running', 'send', 'throw']
有几个属性很突出,即:
[
'__await__',
'close',
'cr_await',
'cr_code',
'cr_frame',
'cr_origin',
'cr_running',
'send',
'throw'
]
在阅读了what does yield (yield) do? 以及生成器的一般工作原理后,我认为send 方法一定是关键。
所以我尝试:
>>> the_actual_coro = coro()
<coroutine object coro at 0x7f5afaf55348>
>>>the_actual_coro.send(None)
它引发了一个有趣的错误:
Original exception was:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration: a value
它实际上在异常中给了我返回值!
所以我认为一个非常基本的循环,嗯,它更像是一个跑步者,可以这样实现:
def run(coro):
try:
coro.send(None)
except StopIteration as e:
return e.value
现在,我可以在同步函数中运行协程,甚至可以在全局范围内运行协程,我不建议这样做。但是,了解运行协程的最简单和最低级别很有趣
>>> run(coro())
'a value'
然而,当 coro 有一些等待时,这会返回 None(这确实是协程的本质)。
我认为这可能是因为事件循环通过将它们分配给期货并单独处理它们来处理它的协程 (coro.cr_frame.f_locals) 的等待对象?我的简单run 函数显然没有提供。在这方面我可能是错的。所以如果我错了,请有人纠正我。