首页 > 解决方案 > Python (3.7) asyncio,带有 while 循环和自定义信号处理程序的工作任务

问题描述

我试图了解无限期运行 asyncio 任务的模式以及自定义循环信号处理程序的不同之处。我使用创建工人,loop.create_task()以便他们同时运行。

在我的普通工人代码中,我正在轮询数据并在数据存在时采取相应的行动。

我正在尝试在信号上优雅地处理关闭过程。传递信号时 - 我再次create_task()使用关闭功能,以便当前正在运行的任务继续,并且在事件循环的下一次迭代中执行关闭。现在 - 当单个工作while循环实际上没有执行任何 IO 或工作时,它会阻止信号处理程序被执行。它永远不会结束并且不会返回执行以便可以运行其他任务。

当我没有将自定义信号处理程序附加到循环并运行该程序时,会传递一个信号并且程序停止。我认为这是一个停止循环本身的主线程。这显然与尝试在运行循环上安排(新)关闭任务不同,因为该运行循环被卡在单个协程中,该协程被阻塞在 while 循环中,并且不会为其他任务提供任何控制或时间。

这种情况有什么标准模式吗?asyncio.sleep()如果没有工作要做,我是否需要用其他东西替换while循环(例如重新安排工作功能本身)?

如果range(5)替换为,range(1, 5)那么所有工作人员都会等待 asyncio.sleep,但如果其中一个没有,那么一切都会被阻止。这种情况如何处理,有没有标准的做法?

下面的代码说明了这个问题。

async def shutdown(loop, sig=None):
    print("SIGNAL", sig)
    tasks = [t for t in asyncio.all_tasks()
             if t is not asyncio.current_task()]

    [t.cancel() for t in tasks]

    results = await asyncio.gather(*tasks, return_exceptions=True)
    # handle_task_results(results)
    loop.stop()


async def worker(intval):
    print("start", intval)
    while True:
        if intval:
            print("#", intval)
            await asyncio.sleep(intval)


loop = asyncio.get_event_loop()

for sig in {signal.SIGINT, signal.SIGTERM}:
    loop.add_signal_handler(
        sig,
        lambda s=sig: asyncio.create_task(shutdown(loop, sig=s)))

workers = [loop.create_task(worker(i)) for i in range(5)]  # this range

loop.run_forever()

标签: python-3.xredissignalspython-asyncioworker

解决方案


推荐阅读