我设法导入/安装了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/

10-15 03:38