我有以下情况:

  • 一些内部类(我无法控制)正在使用 call_soon 执行我的 callback 函数。
  • 在我的 callback 中,我想调用另一个 courotune,但最终以“卡住”回调告终。

  • 我将使用修改后的 Hello World with call_soon() 来演示这一点:

    import asyncio
    
    def hello_world(loop):
        print('Hello')
        # Call some coroutine.
        yield from asyncio.sleep(5, loop=loop)
        print('World')
        loop.stop()
    
    loop = asyncio.get_event_loop()
    
    # Schedule a call to hello_world()
    loop.call_soon(hello_world, loop)
    
    # Blocking call interrupted by loop.stop()
    loop.run_forever()
    loop.close()
    

    当我运行它时,没有打印任何内容并且程序永远不会结束。

    Ctrl+C

    Traceback (most recent call last):
      File "../soon.py", line 15, in <module>
        loop.run_forever()
      File "/usr/lib/python3.4/asyncio/base_events.py", line 276, in run_forever
        self._run_once()
      File "/usr/lib/python3.4/asyncio/base_events.py", line 1136, in _run_once
        event_list = self._selector.select(timeout)
      File "/usr/lib/python3.4/selectors.py", line 432, in select
        fd_event_list = self._epoll.poll(timeout, max_ev)
    KeyboardInterrupt
    

    实际发生了什么,为什么?

    任何正确的方法来做到这一点?

    最佳答案

    您提到的示例演示了如何安排回调。

    如果您使用 yield from 语法,则该函数实际上是一个 coroutine 并且必须对其进行相应的修饰:

    @asyncio.coroutine
    def hello_world(loop):
        print('Hello')
        yield from asyncio.sleep(5, loop=loop)
        print('World')
        loop.stop()
    

    然后,您可以使用 ensure_future 将协程安排为任务:
    loop = asyncio.get_event_loop()
    coro = hello_world(loop)
    asyncio.ensure_future(coro)
    loop.run_forever()
    loop.close()
    

    或者等效地,使用 run_until_complete :
    loop = asyncio.get_event_loop()
    coro = hello_world(loop)
    loop.run_until_complete(coro)
    

    两周后,python 3.5 将正式发布,您将可以使用新的 async / await 语法:
    async def hello_world(loop):
        print('Hello')
        await asyncio.sleep(5, loop=loop)
        print('World')
    

    EDIT :这有点难看,但没有什么能阻止你创建一个回调来安排你的协程:
    loop = asyncio.get_event_loop()
    coro = hello_world(loop)
    callback = lambda: asyncio.ensure_future(coro)
    loop.call_soon(callback)
    loop.run_forever()
    loop.close()
    

    关于python - 从 `call_soon` 回调函数执行协程,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32308382/

    10-16 08:43