python "signal only works in main thread of the main interpreter" 在带有子进程的烧瓶中

python "signal only works in main thread of the main interpreter" in flask with subprocess

我目前正在开发一个烧瓶网络服务器, 并希望在父进程触发 ctrl+c 时使用一个函数来完成子进程的工作流程。

main.py为父进程,直接python3 main.py启动。

并且子进程 (app.py) main.py 之后 subprocess.popen(...) 启动。

# main.py
def get_flask_env():
    flask_env = os.environ.copy()
    if "FLASK_APP" not in flask_env:
        flask_env["FLASK_APP"] = "./server/app.py"
    if "FLASK_ENV" not in flask_env:
        flask_env["FLASK_ENV"] = "development"
    return flask_env

def start_flask():
    flask_env = get_flask_env()
    command = []
    # the command to start app.py, would be: flask run --host 0.0.0.
    command.append(python_command)
    command.append("-m")
    command.append("flask")
    command.append("run")
    command.append("--host")
    command.append("0.0.0.0")
    monitor = subprocess.Popen(command, env=flask_env)

当我启动flask server(app.py)时,我发现flask server中的错误需要处理clear:

def handle_exit(*args):
    # clear multiprocessing here
    pass

然后在app.py中设置signal

signal.signal(signal.SIGTERM,  handle_exit)
signal.signal(signal.SIGINT,  handle_exit)

我在父进程中成功使用了它(main.py),但是如果我在子进程中使用信号时遇到了问题,问题:

signal only works in main thread of the main interpreter

那么如何正确使用信号子进程呢?

已编辑:

目前,我使用 main.py 中的 subprocess.run(...) 通过 linux 命令终止所有多进程:pkill,但这不是跨平台的方式,并且可能会在没有正确等待它完成的情况下终止该过程。

好的。我的想法是这样的。

import atexit
import os
import subprocess


def teardown(process_handle):
    process_handle.terminate() #kill the sub process clean
    process_handle.wait()# wait for graceful exit.


def get_flask_env():
    flask_env = os.environ.copy()
    if "FLASK_APP" not in flask_env:
        flask_env["FLASK_APP"] = "./server/app.py"
    if "FLASK_ENV" not in flask_env:
        flask_env["FLASK_ENV"] = "development"
    return flask_env


def start_flask():
    flask_env = get_flask_env()
    command = []
    # the command to start app.py, would be: flask run --host 0.0.0.
    command.append(python_command)
    command.append("-m")
    command.append("flask")
    command.append("run")
    command.append("--host")
    command.append("0.0.0.0")
    monitor = subprocess.Popen(command, env=flask_env)
    atexit.register(teardown, monitor) #register to execute at exit