python - 使用 gevent.spawn 时弹出错误的应用程序上下文
问题描述
我正在尝试在我的烧瓶应用程序中使用 gevent 运行多个并发下游请求。
我有:
import gevent
from gevent import monkey
monkey.patch_all(thread=False)
from flask import Flask, request, g
app = Flask(__name__, static_folder='static')
和以下代码:
def f1(self):
@copy_current_request_context
def _test(t):
time.sleep(t)
r = requests.get(
'https://webhook.site/d14a41a6-9c6a-4da0-bbe6-3cc660daea3d', params=dict(word='test')
)
return r.status_code
jobs = [gevent.spawn(_test, 5), gevent.spawn(_test, 10)]
results = [job.value for job in gevent.joinall(jobs)]
return None
如果第二个 _test 花费的时间比第一个长,我会收到弹出错误的应用程序上下文错误。
如果我添加另一种方法,例如:
@copy_current_request_context
def _test_bis(t):
from random import randint
time.sleep(t)
r = requests.get(
'https://webhook.site/d14a41a6-9c6a-4da0-bbe6-3cc660daea3d', params=dict(word='test')
)
return r.status_code
并像这样使用它:
jobs = [gevent.spawn(_test_bis, 5), gevent.spawn(_test, 10)]
我没有任何错误。
知道如何解决这个问题吗?
解决方案
这与Flask 的应用程序上下文有关。当您使用 spawn 启动多个 greenlet 时,Flask 不知道哪个应用程序是“当前”应用程序。您已经使用了@copy_current_request_context
装饰器,但它只复制请求上下文并为所有 bg 线程提供新的应用程序上下文。
为避免这种情况,您可以创建一个以通过闭包传递当前应用程序上下文:
def copy_current_app_context(f):
from flask.globals import _app_ctx_stack
appctx = _app_ctx_stack.top
def _(*args, **kwargs):
with appctx:
return f(*args, **kwargs)
return _
或者您可以选择将线程代码包装在 a 中test_request_context
,这样您就可以访问上下文本地变量:
def f1(self):
with app.test_request_context():
def _test(t):
time.sleep(t)
r = requests.get(
'https://webhook.site/d14a41a6-9c6a-4da0-bbe6-3cc660daea3d', params=dict(word='test')
)
return r.status_code
jobs = [gevent.spawn(_test, 5), gevent.spawn(_test, 10)]
results = [job.value for job in gevent.joinall(jobs)]
return None
值得指出的是,线程将具有与原始请求不同的上下文。如果您需要任何有趣的请求数据,在生成线程之前提取这些数据很重要。
推荐阅读
- sql - 在没有时区的情况下在雪花中度过几个月
- javascript - 如何将流量 ID 添加到多个不同的链接?
- mongodb - 如何改进骨料管道
- ansible - 创建一个事实来总结清单中每个主机的内容?
- function - 如何在haskell中实现这个功能?
- java - 线程“AWT-EventQueue-0”java.lang.NullPointerException 中的异常?请帮助我不知道该怎么办
- docker - 将 docker 服务公开给 Web 应用程序的首选安全方法是什么?
- javascript - 样式化组件不传递 dom 属性
- flutter - 如何修复颤振中的无效双精度
- c++ - 无法从内容文件中删除换行符(文本)