繁体   English   中英

为什么这个Python异步脚本永远不会完成?

[英]Why does this Python async script never finish?

我创建了一个MCVE示例,其中包含了我正在处理的更大的代码库,所以有些东西看起来是一种时髦的做事方式,但它们只是最小的版本,所以并不是所有事情都有意义我为什么这样做就是这样。 我已经知道了一些解决方法,而且在这一点上,我大多只是好奇为什么我会看到这种行为。

我有以下脚本,它具有等待未来的异步功能。 然后该脚本拦截一个信号以设置未来结果:

import asyncio
import time
import signal

f = asyncio.Future()
loop = asyncio.get_event_loop()

async def wait_till_signal():
    await f

def send_stop():
    print('stopping', time.time())
    f.set_result(True)
    print('sent')
    print(f.result())

def handle_signal(s, a):
    print('sending stop', time.time())
    send_stop()

signal.signal(signal.SIGINT, handle_signal)

loop.run_until_complete(wait_till_signal())

此脚本正确获取中断,并且似乎正确设置了未来,但由于某种原因,脚本永远不会终止。

要为您重现,只需运行脚本,然后按ctrl + c。 出于某种原因,它永远不会停止

现在这里变得奇怪了。 如果将以下内容添加到脚本的顶部(在定义循环之后),则脚本会停止正常。

async def do_nothing_useful():
     for i in range(30):
         await asyncio.sleep(1)

loop.create_task(do_nothing_useful())

为什么协程在第一种情况下没有获得未来,但它在第二种情况下是否正确?


另外,另一个奇怪的事情是,如果将send_stop函数设置为异步,并将其添加为任务,则永远不会调用它。 (这遵循与上面相同的行为。如果do_nothing_useful()函数在循环上,一切正常,但没有它,它不会)

以下是永远不会调用send_stop的版本:

import asyncio
import time
import signal

f = asyncio.Future()

async def wait_till_signal():
    await f

async def send_stop():
    # this is async only because we are trying to try out crazy things
    print('stopping', time.time())
    f.set_result(True)
    print('sent')
    print(f.result())


def handle_signal(s, a):
    print('sending stop', time.time())
    loop.create_task(send_stop())


signal.signal(signal.SIGINT, handle_signal)

loop = asyncio.get_event_loop()
loop.run_until_complete(wait_till_signal())
print('done')

并且脚本永远不会打印stopping


我在Linux上的python 3.5.3和3.6上试过这个

添加唤醒循环的信号处理程序的正确方法是使用loop.add_signal_handler 这将确保select()唤醒以处理信号。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM