You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python类实例执行后销毁,无法终止Flask子进程问题求助

解决方案

核心思路

把Flask子进程的管理逻辑封装成类,让主进程持有类实例的引用(避免实例被销毁),同时在类中实现启动、停止方法,再通过注册退出钩子确保主进程终止时同步终止子进程。Windows下通过设置CPU亲和性实现核心独占。

代码修改

1. 重构flaskSubprocess.py为类管理模式

import subprocess
import sys
import psutil
from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello():
    return "Hello from Flask!"

def run_flask():
    # 必须关闭debug模式,否则Flask会自动启动子进程,导致亲和性设置失效
    app.run(host='0.0.0.0', port=5000, debug=False)

class FlaskSubprocessManager:
    def __init__(self):
        self.flask_process = None

    def start_server(self, core_id=0):
        # 启动Flask子进程,创建独立进程组(Windows下方便批量终止)
        self.flask_process = subprocess.Popen(
            [sys.executable, '-c', 'from flaskSubprocess import run_flask; run_flask()'],
            creationflags=subprocess.CREATE_NEW_PROCESS_GROUP
        )
        # 设置子进程独占指定核心
        proc = psutil.Process(self.flask_process.pid)
        proc.cpu_affinity([core_id])  # 传入单个核心ID,比如0号核心
        print(f"Flask子进程启动,PID: {self.flask_process.pid},绑定核心: {core_id}")

    def stop_server(self):
        if self.flask_process and self.flask_process.poll() is None:
            # Windows下发送CTRL_BREAK_EVENT终止整个进程组
            self.flask_process.send_signal(subprocess.CTRL_BREAK_EVENT)
            self.flask_process.wait()
            print("Flask子进程已终止")

2. 修改main.py保留实例并注册退出钩子

import atexit
from flaskSubprocess import FlaskSubprocessManager

# 全局保留实例,避免被垃圾回收
flask_manager = FlaskSubprocessManager()

def cleanup_flask():
    flask_manager.stop_server()

if __name__ == "__main__":
    # 启动Flask子进程,绑定到0号核心(可根据需要修改核心ID)
    flask_manager.start_server(core_id=0)
    # 注册退出钩子:主进程终止时自动停止Flask子进程
    atexit.register(cleanup_flask)

    # 主进程业务逻辑示例
    try:
        input("按Enter键终止主进程...\n")
    except KeyboardInterrupt:
        pass

关键说明

  • 保留实例引用:通过全局变量保存FlaskSubprocessManager实例,避免函数调用后实例被销毁,确保随时能调用stop_server。
  • 核心独占:使用psutil的cpu_affinity方法,限制子进程仅在指定核心运行(Windows系统有效),需先安装psutil:pip install psutil。
  • 进程终止:创建子进程时使用CREATE_NEW_PROCESS_GROUP,配合CTRL_BREAK_EVENT信号可一次性终止Flask相关的所有进程,避免残留。
  • 自动清理:通过atexit.register注册清理函数,无论主进程是正常退出还是被中断,都会自动调用stop_server终止Flask子进程。

内容的提问来源于stack exchange,提问作者sharkyenergy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 07:32:05