我正试图在我的flask __init__.py中实现多处理或线程,以实现将为我处理一些后端工作的子进程。然而,我似乎无法将应用程序上下文传递给子进程,并且现有的库专注于请求-我需要这个进程在运行flask时开始并行运行,而不是更晚。
下面是我的__init__.py代码(不包括不相关页面的设置,我一次只使用一个实现):
import os
from multiprocessing import Process
from threading import Thread
from flask_executor import Executor
from flask import Flask
from . import backend
def create_app():
app = Flask(__name__, instance_relative_config=True)
# Multiprocessing Implementation:
p = Process(target=backend.start)
p.start()
# Threading Implementation:
thread = Thread(target=backend.start)
thread.daemon = True
thread.start()
# Flask Executor Implementation:
executor = Executor(app)
executor.submit(backend.start)
return app
这是我的backend.py,由子进程调用:
from datetime import datetime
from flask import g, request, session
from flaskr.db import log
def start(app=None):
print("nBackend Startedn")
log("INFO","Backend Started")
while True:
pass
后端代码调用一个日志函数,该函数在我的普通flask进程中的请求中调用时工作。
我的多进程和线程实现不起作用,因为我无法将应用程序上下文传递给子进程。Process(target=backend.start, args=app)
或Thread(target=backend.start, args=app)
给我一个错误,TypeError: 'Flask' object is not iterable
。我不能在start函数中添加@with_appcontext标志,因为它不是一个请求。
My Flask Executor将应用程序上下文传递给子进程,但它也不能成功,因为它不是从请求中调用的:
Traceback (most recent call last):
File "c:...pythonpython39librunpy.py", line 197, in _run_module_as_main
return _run_code(code, main_globals, None,
File "c:...pythonpython39librunpy.py", line 87, in _run_code
exec(code, run_globals)
File "C:...PythonPython39Scriptsflask.exe__main__.py", line 7, in <module>
File "c:...pythonpython39libsite-packagesflaskcli.py", line 988, in main
cli.main()
File "c:...pythonpython39libsite-packagesflaskcli.py", line 579, in main
return super().main(*args, **kwargs)
File "c:...pythonpython39libsite-packagesclickcore.py", line 1055, in main
rv = self.invoke(ctx)
File "c:...pythonpython39libsite-packagesclickcore.py", line 1657, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "c:...pythonpython39libsite-packagesclickcore.py", line 1404, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "c:...pythonpython39libsite-packagesclickcore.py", line 760, in invoke
return __callback(*args, **kwargs)
File "c:...pythonpython39libsite-packagesclickdecorators.py", line 84, in new_func
return ctx.invoke(f, obj, *args, **kwargs)
File "c:...pythonpython39libsite-packagesclickcore.py", line 760, in invoke
return __callback(*args, **kwargs)
File "c:...pythonpython39libsite-packagesflaskcli.py", line 850, in run_command
app = DispatchingApp(info.load_app, use_eager_loading=eager_loading)
File "c:...pythonpython39libsite-packagesflaskcli.py", line 299, in __init__
self._load_unlocked()
File "c:...pythonpython39libsite-packagesflaskcli.py", line 333, in _load_unlocked
self._app = rv = self.loader()
File "c:...pythonpython39libsite-packagesflaskcli.py", line 389, in load_app
app = locate_app(import_name, name)
File "c:...pythonpython39libsite-packagesflaskcli.py", line 251, in locate_app
return find_best_app(module)
File "c:...pythonpython39libsite-packagesflaskcli.py", line 77, in find_best_app
app = app_factory()
File "C:...flaskr__init__.py", line 51, in create_app
executor.submit(backend.start)
File "c:...pythonpython39libsite-packagesflask_executorexecutor.py", line 162, in submit
fn = self._prepare_fn(fn)
File "c:...pythonpython39libsite-packagesflask_executorexecutor.py", line 122, in _prepare_fn
fn = copy_current_request_context(fn)
File "c:...pythonpython39libsite-packagesflaskctx.py", line 172, in copy_current_request_context
raise RuntimeError(
RuntimeError: This decorator can only be used when a request context is active, such as within a view function.
我如何才能正确地实现这一点?
我找到了一个解决这个问题的方法。我将这段代码添加到我的backend.py:
from flask import Blueprint
from threading import Thread
bp = Blueprint('backend', __name__)
def backend(app):
thread = Thread(target=start, args=(app,))
thread.daemon = True
thread.start()
然后我在__init__.py中将backend.backend(app)
添加到我的create_app()函数中,就在我的函数结束之前。这将从backend.py调用我的backend()函数并传递应用程序上下文,这个函数启动我的子进程。