AttributeError: невозможно выбрать локальный объект «Flask.__init__.<locals>.<lambda>» из-за многопроцессорности

Я пытаюсь запустить веб-сервер внутри процесса. (Отвечайте на этот вопрос, почему мне нужно использовать многопроцессорность: Остановка даш-сервера внутри потока не работает)

Это небольшой пример:

import logging
from dash import html, Dash
from flask import Flask
from multiprocessing import Process

############################## setup logger #############################
logging.basicConfig(
    level=logging.INFO,
    format = "%(asctime)s [%(threadName)s, %(levelname)s] %(message)s",
    handlers=[
        logging.FileHandler("logs.log"),
        logging.StreamHandler()
    ]
)
#########################################################################

class test:
    def __init__(self):
        flask_app = Flask(__name__)
        self.app = Dash(__name__, server=flask_app)

        # Define a simple layout
        self.app.layout = html.Div(children=[
            html.H1(children='Hello Dash'),
            html.P(children='This is a simple Dash app for testing.'),
            html.Button('Click Me', id='button')
        ])

    def prepare_webserver(self):      
        self.server_proc = Process(target=self.run_server, 
                                   name='dash_server', 
                                   daemon=True)
        self.server_proc.start()

    # Function to run the server
    def run_server(self):
        logging.info("Starting Dash server")
        self.app.run_server(debug=True, use_reloader=False)

if __name__ == "__main__":
    sim_manager = test()
    sim_manager.prepare_webserver()

И я получаю следующую ошибку: Traceback (последний вызов последний):

  File "C:\Users\username\Desktop\Projects\python_framework\optimization_framework\test2.py", line 42, in <module>
    sim_manager.prepare_webserver()
  File "C:\Users\username\Desktop\Projects\python_framework\optimization_framework\test2.py", line 33, in prepare_webserver
    self.server_proc.start()
  File "C:\Users\username\AppData\Local\Programs\Python\Python310\lib\multiprocessing\process.py", line 121, in start
    self._popen = self._Popen(self)
  File "C:\Users\username\AppData\Local\Programs\Python\Python310\lib\multiprocessing\context.py", line 224, in _Popen
    return _default_context.get_context().Process._Popen(process_obj)
  File "C:\Users\username\AppData\Local\Programs\Python\Python310\lib\multiprocessing\context.py", line 327, in _Popen
    return Popen(process_obj)
  File "C:\Users\username\AppData\Local\Programs\Python\Python310\lib\multiprocessing\popen_spawn_win32.py", line 93, in __init__
    reduction.dump(process_obj, to_child)
  File "C:\Users\username\AppData\Local\Programs\Python\Python310\lib\multiprocessing\reduction.py", line 60, in dump
    ForkingPickler(file, protocol).dump(obj)
AttributeError: Can't pickle local object 'Flask.__init__.<locals>.<lambda>'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "C:\Users\username\AppData\Local\Programs\Python\Python310\lib\multiprocessing\spawn.py", line 116, in spawn_main
    exitcode = _main(fd, parent_sentinel)
  File "C:\Users\username\AppData\Local\Programs\Python\Python310\lib\multiprocessing\spawn.py", line 126, in _main
    self = reduction.pickle.load(from_parent)
EOFError: Ran out of input

🤔 А знаете ли вы, что...
Python позволяет создавать сценарии для автоматизации задач и обработки данных.


65
1

Ответ:

Решено

Почти наверняка self нельзя мариновать, поэтому вы не можете использовать self.run_server в качестве цели.

Попробуйте создать run_server() статический метод.

    @staticmethod
    # Function to run the server
    def run_server():
        server = Test()
        logging.info("Starting Dash server")
        server.app.run_server(debug=True, use_reloader=False)

Нет никаких причин, по которым новому процессу нужно передавать настроенный существующий сервер, а не создавать свой собственный.