等待未来从未到达,尽管 set_result() 被调用

awaiting future never reached, although set_result() is called

我的例子class只使用了两种方法,

想法是在收到信号后使用 python 信号处理程序调用 stop() 函数。 stop() 然后设置 run() 正在等待的 Future() 的结果。到目前为止一切顺利,但这行不通。实际上,run() 方法从未注意到 Future() 已完成。

示例代码:

import asyncio
import signal


class Foo:
    def __init__(self):
        self._stop = None

    async def run(self):
        print(f"1. starting foo")
        self._stop = asyncio.Future()
        await self._stop
        print(f"4. 'stop' called, canceling running tasks...")

    def stop(self):
        print(f"3. stopping foo")
        self._stop.set_result(None)


f = Foo()
loop = asyncio.new_event_loop()


def signal_handler(_, __):
    print(f"2. signal handler: call Foo.stop()")
    f.stop()


signal.signal(signal.SIGINT, signal_handler)
loop.run_until_complete(f.run())
print(f"5. bye")

输出为:

1. starting foo
2. signal handler: call Foo.stop()
3. stopping foo

就是这样。永远不会调用第四个打印条目。虽然设置结果后 self._stop 的 Future 是 done.

有谁知道我做错了什么以及我错过了什么? 任何帮助将不胜感激!

我无法重现您的问题,但它很可能会在不同的操作系统上发生。

根据 loop.add_signal_handler:

Unlike signal handlers registered using signal.signal(), a callback registered with this function is allowed to interact with the event loop.

导致这些问题的罪魁祸首通常是事件循环没有从外部输入唤醒。

您的问题有 2 个解决方案:

  1. 如果您使用的是 unix,请将 signal.signal() 更改为 loop.add_signal_handler()
  2. 如果不是,请尝试将 f.stop() 更改为 loop.call_soon_threadsafe(f.stop)。它将确保事件循环正确唤醒。

不管怎样,使用 asyncio.new_event_loop() 并且没有将循环分配给线程或正确清理会引起几个不同的问题。我建议你使用 asyncio.run().