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

时间:2014-09-17 16:45:12

标签: python flask uwsgi gevent

我正在尝试访问衍生的Greenlet中的flask请求对象。这是代码:

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_async()中的第一行会抛出此错误:

RuntimeError: working outside of request context

如何允许do_sync()“在请求上下文之外工作”?

我尝试过的事情:

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

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

  • 使用copy_current_request_context装饰器复制请求对象。这有效 但它变得阻塞了。在do_async完成后,才会发送响应 虽然它在一个gevent线程中。

软件版本:

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

修改

这是我在试图“解锁”copy_current_request_context装饰器时注意到的。这是代码:

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_async()中没有gevent.sleep(0.001)行,该函数可以工作,但是块(在我正在模拟的“真正的”do_async()代码中,它会阻塞大约8秒)。使用该行,该函数不会阻塞,但请求现在为空。

0 个答案:

没有答案