【Flask】AssertionError: Popped wrong app context.
现象:
Traceback (most recent call last):
File "src\\gevent\\greenlet.py", line 908, in gevent._gevent_cgreenlet.Greenlet.run
File "************\venv\lib\site-packages\flask\ctx.py", line 157, in wrapper
return f(*args, **kwargs)
File "************\venv\lib\site-packages\flask\ctx.py", line 464, in __exit__
self.auto_pop(exc_value)
File "************\venv\lib\site-packages\flask\ctx.py", line 452, in auto_pop
self.pop(exc)
File "************\venv\lib\site-packages\flask\ctx.py", line 438, in pop
app_ctx.pop(exc)
File "************\venv\lib\site-packages\flask\ctx.py", line 241, in pop
assert rv is self, "Popped wrong app context. (%r instead of %r)" % (rv, self)
AssertionError: Popped wrong app context. (<flask.ctx.AppContext object at 0x000001DD7CF510F0> instead of <flask.ctx.AppContext object at 0x000001DD7CFBA5C0>)
2023-05-31T02:26:16Z <Greenlet at 0x1dd7cf79048: handle_data(<Queue at 0x1dd7cf7de80>, sid_spaces={'ws': <geventwebsocket.websocket.WebSocket object)> failed with AssertionError
- 在处理完毕相关事情,外部连接断开时,移除对栈中本次协程上下文
- 不影响业务逻辑。
原因分析:
在一次请求事件中,使用gevent进行异步非阻塞任务,并使用copy_current_request_context进行request、g等上下文拷贝传递,结束时app上下文不存在,引发app栈移除失败
- 使用时条件:flask、gevent、copy_current_request_context
解决办法:
- 解决策略:在创建协程时,拷贝request的等上下文之前,应创建app上下文
- 方案:
def copy_current_app_context(f):
from flask.globals import _app_ctx_stack
tx = _app_ctx_stack.top
def wrapper(*args, **kwargs):
with tx:
return f(*args, **kwargs)
return wrapper
copy_current_app_context 要在 request、g等拷贝前,即:copy_current_request_context