无法实现Python Flask服务器多进程部署问题求助
问题分析
报错AttributeError: Can't pickle local object 'Flask.__init__.<locals>.<lambda>'的核心原因是:Windows系统下Python多进程默认使用spawn启动方式,需要将进程的目标函数和参数序列化(pickle)后传递给子进程。但你的代码中将APIServer实例(包含Flask app对象)作为参数传给子进程,而Flask内部会生成局部lambda函数,这类对象无法被pickle序列化,导致启动失败。
解决方案
重构代码,让子进程独立初始化Flask应用和相关配置,避免传递包含无法序列化对象的实例。以下是修改后的关键代码:
修改后的APICommunications.py
import ProcessBuilder as pb import ServiceLogger as sl import SystemRecovery as sr from flask import Flask, Response from waitress import serve from flask_cors import CORS class EndpointAction(object): def __init__(self, action): self.action = action self.logger = sl.ServiceLogger() self.response = Response(status=200, headers={}) def __call__(self, *args): self.action() return self.response def run_server(): # 子进程内独立创建Flask app及相关配置 debug = sr.Recovery().debug port = sr.Recovery().api_port host = '127.0.0.1' app = Flask(__name__) CORS(app, resources={r"/api/*": {"origins": "*"}}) # 注册端点逻辑(可根据需求扩展) def register_endpoints(app_inst): def test_handler(): print("Test endpoint triggered") app_inst.add_url_rule('/api/test', 'test', EndpointAction(test_handler)) register_endpoints(app) serve(app, port=port, host=host) class APIServer: def __init__(self): self.server = None self.logger = sl.ServiceLogger() # 创建进程时指向独立的run_server函数,无需传递self self.server = pb.ProcessBuilder().create_process(run_server) def start(self): self.server.start() def terminate(self): self.server.kill() return None if __name__ == "__main__": a = APIServer() a.start() print("heyy") a.terminate() print("process killed")
关键修改点
- 提取独立的
run_server函数,让子进程内部完成Flask app初始化、CORS配置和端点注册,彻底避免传递包含无法序列化对象的APIServer实例。 - 创建进程时不再传递
self作为参数,消除pickle序列化的需求。 - 主逻辑放在
if __name__ == "__main__":块中,符合Windows多进程的启动规范,避免子进程重复执行初始化代码。
补充说明
如果需要主进程与子进程共享配置参数(如端口、主机地址),可以将这些参数单独传递给run_server,而非传递整个实例:
def run_server(port, host): app = Flask(__name__) # ...其他初始化逻辑 serve(app, port=port, host=host) # 在APIServer.__init__中: port = sr.Recovery().api_port host = '127.0.0.1' self.server = pb.ProcessBuilder().create_process(run_server, args=[port, host])
这种方式既保证配置一致性,又规避了复杂对象序列化的问题。
内容的提问来源于stack exchange,提问作者SaM AroRa
相关产品推荐
相关产品推荐

