【问题标题】:Kill a python subprocess that does not return杀死一个不返回的python子进程
【发布时间】:2021-12-26 19:34:46
【问题描述】:

TLDR 我想杀死一个像 top 这样仍在运行的子进程
我正在使用 Fastapi 在输入上运行命令。例如,如果我输入 top 我的程序运行命令,但由于它没有返回,此时我必须使用时间延迟然后杀死/终止它。但是我希望能够在它仍在运行时将其杀死。但是目前它不会运行我的 kill 命令,直到时间用完。 这是当前运行进程的代码:

@app.put("/command/{command}")
async def run_command(command: str):
    subprocess.run([command], shell=True, timeout=10)
    return {"run command"}

杀死它

@app.get("/stop")
async def stop():
    proc.kill()
    return{"Stop"}

我是 fastapi 的新手,所以我会很感激任何帮助

【问题讨论】:

    标签: python subprocess fastapi


    【解决方案1】:

    这是因为 subprocess.run 正在阻塞自己 - 您需要在后台运行 shell 命令,例如如果你已经开启了 asnycio 循环,你可以使用subprocesses

    import asyncio
    
    process = None
    @app.get("/command/{command}")
    async def run_command(command: str):
        global process
        process = await asyncio.create_subprocess_exec(
            command, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
        )
        return {"run command"}
    
    @app.get("/stop")
    async def stop():
        process.kill()
        return {"Stop"}
    

    Popen

    from subprocess import Popen
    
    process = None
    @app.get("/command/{command}")
    async def run_command(command: str):
        global process
        process = Popen([command])  # something long running
        return {"run command"}
    

    添加超时选项可能很棘手,因为您不想等到它完成(您确实可以使用wait_for 函数),而是希望在特定时间后终止进程。据我所知,最好的选择是安排其他负责杀死主要进程的进程。带有 asyncio 的代码可能如下所示:

    @app.get("/command/{command}")
    async def run_command(command: str):
        global process
        process = await asyncio.create_subprocess_exec(
            command, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
        )
        loop = asyncio.get_event_loop()
        # We schedule here stop coroutine execution that runs after TIMEOUT seconds
        loop.call_later(TIMEOUT, asyncio.create_task, stop(process.pid))
    
        return {"run command"}
    
    @app.get("/stop")
    async def stop(pid=None):
        global process
        # We need to make sure we won't kill different process
        if process and (pid is None or process.pid == pid):
            process.kill()
            process = None
        return {"Stop"}
    

    【讨论】:

    • 那么它如何在 10 秒后停止,就好像我告诉它休眠程序会等到休眠后运行停止一样?
    • 你的意思是如果进程持续更长的时间,你想杀死它?
    • 是的。例如,如果我运行 top 我希望它在 30 秒后自动停止,但如果我像以前一样使用 kill 命令,它会更快地停止。但是我不能使用 time.sleep(30) 因为我的 kill 命令在 30 秒之后才会起作用。
    • @CodingNewbie 抱歉耽搁了,我更新了答案。让我知道它对你有用吗!
    最近更新 更多