如何使用uwsgi/gevent/flask创建一个使用请求上下文的异步任务?

2024-03-29 14:48:27 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试访问生成的Greenlet中的flask request对象。代码如下:

import gevent
from flask import Flask, request, render_template

app = Flask(__name__)

@app.route('/async')
def async():
  gevent.spawn(do_async)

  return 'OK'

def do_async():
  html = render_template('async.html', args=request.args)
  print html

当我访问服务器时,do\u async()中的第一行抛出以下错误:

^{pr2}$

如何允许do\u sync()在“请求上下文之外工作”?在

我尝试过的事情:

  • 在不同的地方使用with app.app_context():

  • 创建一个新的请求对象并将其作为参数传递给do\u async(),使用
    req = app.request_context(request.environ)
    这将引发错误
    AttributeError: 'RequestContext' object has no attribute 'args'

  • copy_current_request_context修饰符复制了请求对象。这很管用 但随后就变成了阻塞。直到do\u async完成后才会发送响应 虽然它在一个gevent线程中。

软件版本:

  • python 2.7.5
  • uwsgi 2.0版
  • gevent 1.0.1版
  • 烧瓶0.10.1

编辑:

当我试图“解除”装饰器的阻塞时,我注意到了这一点。代码如下:

import gevent
from flask import Flask, request, render_template
from flask import copy_current_request_context

app = Flask(__name__)

@app.route('/async')
def async():

  @copy_current_request_context
  def wrap_do_async():
    do_async()

  gevent.spawn(wrap_do_async)

  return 'OK'

def do_async():
  gevent.sleep(0.001)    # Added to 'unblock' copy_current_request_context
  html = render_template('async.html', args=request.args)
  print html

如果没有do\u async()中的gevent.sleep(0.001)行,该函数可以工作,但是会阻塞(在我这里模拟的“真正的”do\u async()代码上,它阻塞了大约8秒钟)。对于行,函数不会阻塞,但请求现在是空的。在


Tags: importappflaskasyncrequestdefhtmlcontext