我设法导入/安装了Twisted的asyncioreactor
并执行了一个简单的异步函数:
from twisted.internet import asyncioreactor
asyncioreactor.install()
from twisted.internet import task
from twisted.internet.defer import inlineCallbacks
from twisted.internet.defer import ensureDeferred
async def sleepy(reactor):
print("SLEEPING")
await task.deferLater(reactor, 3.0, lambda: None)
print("done sleep")
return 42
@task.react
def main(reactor):
d = ensureDeferred(sleepy(reactor))
d.addCallback(print)
return d
我想在上述代码中混合一个asyncio库,例如
asyncio.sleep
。我尝试了以下方法:from twisted.internet import asyncioreactor
asyncioreactor.install()
from twisted.internet import task
from twisted.internet.defer import inlineCallbacks
from twisted.internet.defer import ensureDeferred
import asyncio
async def sleepy(reactor):
print("SLEEPING")
await asyncio.sleep(3)
print("done sleep")
return 42
@task.react
def main(reactor):
d = ensureDeferred(sleepy(reactor))
d.addCallback(print)
return d
产生以下错误:
$ python test.py
SLEEPING
main function encountered error
Traceback (most recent call last):
File "test.py", line 16, in <module>
@task.react
File "/Users/blz/.pyenv/versions/3.6.0/lib/python3.6/site-packages/twisted/internet/task.py", line 908, in react
finished = main(_reactor, *argv)
File "test.py", line 18, in main
d = ensureDeferred(sleepy(reactor))
File "/Users/blz/.pyenv/versions/3.6.0/lib/python3.6/site-packages/twisted/internet/defer.py", line 823, in ensureDeferred
return _inlineCallbacks(None, coro, Deferred())
--- <exception caught here> ---
File "/Users/blz/.pyenv/versions/3.6.0/lib/python3.6/site-packages/twisted/internet/defer.py", line 1301, in _inlineCallbacks
result = g.send(result)
File "test.py", line 11, in sleepy
await asyncio.sleep(3)
File "/Users/blz/.pyenv/versions/3.6.0/lib/python3.6/asyncio/tasks.py", line 476, in sleep
return (yield from future)
builtins.AssertionError: yield from wasn't used with future
我想很公平,所以我尝试将
await asyncio.sleep(3)
与await ensureDeferred(asyncio.sleep(3))
和await asyncio.ensure_future(asyncio.sleep(3))
交换,但是我得到了完全相同的错误。如何安排aio协程(和/或
Future
)在与asyncioreactor
使用的事件循环上运行? 最佳答案
所以我尝试用await交换await asyncio.sleep(3)
确保Deferred(asyncio.sleep(3))并等待
asyncio.ensure_future(asyncio.sleep(3))
您快到了,应该将两者结合起来,并使用Deferred.fromFuture
而不是ensureDeferred
:
await Deferred.fromFuture(asyncio.ensure_future(asyncio.sleep(3)))
规则是,由Twisted事件循环运行的代码只能在
Deferred
上等待,而由asyncio事件循环运行的代码仅在asyncio Future
上等待(一个人总是可以在其他协程对象上等待(来自async def
函数调用的结果),但是该链最终会导致到Deferred/Future
)。要从asyncio Future
转换为Deferred
,请使用Deferred.fromFuture
,并使用Future
转换为asyncio Deferred.asFuture
。关于interop - 如何在Twisted的asyncioreactor之上运行asyncio库代码?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42317477/