Turbo Flask多线程应用上下文

huangapple go评论39阅读模式
英文:

Turbo Flask Multithreading Application Context

问题

我目前正在开发一个Flask Web应用程序,该应用程序在后台线程中持续扫描本地网络,并且我正在使用Turbo Flask来将更新的结果推送到请求的视图中。

一切运行正常,但现在我在尝试使用Flask应用工厂方法将任务拆分到不同模块时遇到了问题:每当扫描线程执行时,我会收到一个 RuntimeError: Working outside of application context 错误,即使在线程函数内部使用 with current_app.app_context():

这是我的 __init__.py 文件:

from flask import Flask
from turbo_flask import Turbo
import threading

# 全局库
turbo = Turbo()

def init_app():
    # 创建和配置应用程序
    app = Flask(__name__, instance_relative_config=False)
    app.config.from_object('config.Config')

    # 初始化插件
    turbo.init_app(app)

    with app.app_context():
        from . import control
        control.ctrl_init(turbo)

        @app.before_first_request
        def before_first_request():
            threading.Thread(target=control.ext_updater).start()

        return app

这是我的精简 control.py 文件:

from flask import (
    Blueprint, flash, g, redirect, render_template, request, session, url_for, current_app
)
from turbo_flask import Turbo
import os, click, requests
import nmap

turbo = Turbo()

def ctrl_init(turboa):
    turbo = turboa

def ext_updater():
    # 启动线程不断查找外部机器
    with current_app.app_context():
        while True:
            ping_guests()
            turbo.push(turbo.replace(render_template("external_machines.html"), 'guests'))

def ping_guests():
    # 网络扫描代码被省略

我实际上不确定如何正确启动具有应用程序上下文的线程,而且我猜测将 turbo 对象传递给 ctrl_init 函数也不是一个干净的方式,但我有点迷茫,希望能得到任何帮助!

错误首次出现在 control.ext_updater 中的 with current_app.app_context():,但删除它后,调用 turbo.push 时仍会引发相同的错误。

英文:

I am currently developing a flask webapp that continuously scans the local network in a background thread and I am using Turbo Flask to push the updated results in a request's view.

Everything works fine but now I am having trouble splitting the tasks in different modules using the flask application factory approach: whenever the scanning thread is executed I get an RuntimeError: Working outside of application context. even when using with current_app.app_context(): inside the thread function.

Here is my __init__.py:

from flask import Flask
from turbo_flask import Turbo
import threading


# global libraries
turbo = Turbo()

def init_app():
    # create and configure the app
    app = Flask(__name__, instance_relative_config=False)
    app.config.from_object('config.Config')

    # init plugins
    turbo.init_app(app)

    with app.app_context():
        from . import control
        control.ctrl_init(turbo)

        @app.before_first_request
        def before_first_request():
            threading.Thread(target=control.ext_updater).start()

        return app

And this is my reduced control.py

from flask import (
    Blueprint, flash, g, redirect, render_template, request, session, url_for, current_app
)
from turbo_flask import Turbo
import os, click, requests
import nmap

turbo = Turbo()

def ctrl_init(turboa):
	turbo = turboa

def ext_updater():
	# start thread constantly looking for external machines
	with current_app.app_context():
		while True:
			ping_guests()
			turbo.push(turbo.replace(render_template("external_machines.html"), 'guests'))

def ping_guests():
	# network scanning code ommited

I'm actually not sure how to properly start the thread with the application context, and I guess passing the turbo object to the ctrl_init function is also not a neat way but I'm a little lost here and would appreciate any help!

The error is first thrown at the with current_app.app_context(): in control.ext_updater but also removing it throws the same error when calling turbo.push.

答案1

得分: 0

我明白了,我让它能够在创建更新程序线程时传递应用对象:

def ext_updater(app, turbo):
    with app.app_context():
        while True:
            ping_guests()
            turbo.push(turbo.replace(render_template("external_machines.html"), 'guests'))

然后使用以下方式调用它:threading.Thread(target=control.ext_updater, args=(app, turbo)).start()

不过,为什么在线程中不能使用current_app

英文:

Okay, I got it working passing the app object along with creating the updater thread:

def ext_updater(app, turbo):
with app.app_context():
	while True:
		ping_guests()
		turbo.push(turbo.replace(render_template("external_machines.html"), 'guests'))

And call it with threading.Thread(target=control.ext_updater, args=(app, turbo)).start()

However, why doesn't it work with current_app in the thread?

huangapple
  • 本文由 发表于 2023年3月4日 05:42:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/75632123.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定