使用具有应用程序上下文的 Flask 实现线程

问题描述 投票:0回答:1

我正在尝试在我的烧瓶 __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 Started\n")
    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
。我无法将 @with_appcontext 标志添加到启动函数,因为它不是请求。

我的 Flask Executor 将应用程序上下文传递给子流程,但它也无法成功,因为它不是从请求中调用的:

Traceback (most recent call last):
  File "c:\...\python\python39\lib\runpy.py", line 197, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "c:\...\python\python39\lib\runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "C:\...\Python\Python39\Scripts\flask.exe\__main__.py", line 7, in <module>
  File "c:\...\python\python39\lib\site-packages\flask\cli.py", line 988, in main
    cli.main()
  File "c:\...\python\python39\lib\site-packages\flask\cli.py", line 579, in main
    return super().main(*args, **kwargs)
  File "c:\...\python\python39\lib\site-packages\click\core.py", line 1055, in main
    rv = self.invoke(ctx)
  File "c:\...\python\python39\lib\site-packages\click\core.py", line 1657, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "c:\...\python\python39\lib\site-packages\click\core.py", line 1404, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "c:\...\python\python39\lib\site-packages\click\core.py", line 760, in invoke
    return __callback(*args, **kwargs)
  File "c:\...\python\python39\lib\site-packages\click\decorators.py", line 84, in new_func
    return ctx.invoke(f, obj, *args, **kwargs)
  File "c:\...\python\python39\lib\site-packages\click\core.py", line 760, in invoke
    return __callback(*args, **kwargs)
  File "c:\...\python\python39\lib\site-packages\flask\cli.py", line 850, in run_command
    app = DispatchingApp(info.load_app, use_eager_loading=eager_loading)
  File "c:\...\python\python39\lib\site-packages\flask\cli.py", line 299, in __init__
    self._load_unlocked()
  File "c:\...\python\python39\lib\site-packages\flask\cli.py", line 333, in _load_unlocked
    self._app = rv = self.loader()
  File "c:\...\python\python39\lib\site-packages\flask\cli.py", line 389, in load_app
    app = locate_app(import_name, name)
  File "c:\...\python\python39\lib\site-packages\flask\cli.py", line 251, in locate_app
    return find_best_app(module)
  File "c:\...\python\python39\lib\site-packages\flask\cli.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:\...\python\python39\lib\site-packages\flask_executor\executor.py", line 162, in submit
    fn = self._prepare_fn(fn)
  File "c:\...\python\python39\lib\site-packages\flask_executor\executor.py", line 122, in _prepare_fn
    fn = copy_current_request_context(fn)
  File "c:\...\python\python39\lib\site-packages\flask\ctx.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.

我该如何正确实施?

python python-3.x flask python-multithreading
1个回答
0
投票

我找到了解决这个问题的方法。我将此代码添加到我的 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()

然后,我将

backend.backend(app)
添加到 __init__.py 中的 create_app() 函数中,就在函数结束之前。这将从 backend.py 调用我的 backend() 函数并传递应用程序上下文,并且该函数启动我的子进程。

© www.soinside.com 2019 - 2024. All rights reserved.