使用asyncio为python子流程“关闭”事件侦听器

2024-05-15 12:28:31 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图将事件侦听器附加到python子流程,该子流程在流程关闭/退出时调用。回调将重新启动子流程,并将相同的事件侦听器附加到新的事件侦听器

类似于从node.js中的child_process调用.on的东西

我已经知道了。但理想情况下,我希望使用^{}而不是在单独的线程中运行每个事件侦听器

我在想这样的事情-

from asyncio import subprocess as asubprocess
from typing import Callable, Awaitable

async def handle_close(proc: asubprocess.Process, spawner: Callable[[], Awaitable[asubprocess.Process]]):
    while True:
        await proc.wait()
        proc = await spawner()

(此函数还可以扩展为获取进程及其各自的生成程序的列表,并在所有进程上asyncio.wait,一旦其中任何进程停止,它们将重新启动并重复该进程)

proc参数将是由asubprocess.create_subprocess_exec返回的进程,spawner将是一个重新启动该子进程的异步函数。(或任何其他回调)

唯一的问题是,我不知道如何在后台运行它,而不让async污染我的整个代码库。理想情况下,将有多个子流程在后台需要它们自己的handle_close。当所有这些处理程序都在运行时,不应阻止调用方代码

在我自己的用例中,我不需要进程句柄来丢弃这些句柄,只要进程保持运行并在停止时重新启动,并且生成所有进程的调用方代码可以控制其他事情,就可以了


Tags: 代码fromimportasyncio进程事件情况流程
1条回答
网友
1楼 · 发布于 2024-05-15 12:28:31

The only issue is, I don't know how to run this in the background without polluting my entire codebase with async.

这句话并不完全清楚实际的约束是什么,即您愿意使用异步代码走多远。通常,假定使用asyncio的程序在asyncio事件循环内运行,然后整个程序是异步的,即使用回调和/或协同路由。但是,如果使用块代码和线程的代码库很大,也可以在单独的线程中引入asyncio。例如:

_loop = asyncio.new_event_loop()
def _run():
    asyncio.set_event_loop(_loop)
    _loop.run_forever()
threading.Thread(target=_run, daemon=True).start()

def async_submit(coro):
    return asyncio.run_coroutine_threadsafe(coro, _loop)

当事件循环在后台运行时,您可以从阻塞代码向其提交任务。例如:

from typing import List

async def handle_process(cmd: List[str]):
    while True:
        p = await asubprocess.create_subprocess_exec(*cmd)
        await p.wait()
        print('restarting', cmd)

# tell the event loop running in the background to respawn "sleep 1":
async_submit(handle_process(["sleep", "1"]))

请注意,与事件循环的所有交互都必须通过run_coroutine_threadsafe或其表亲call_soon_threadsafe执行

相关问题 更多 >