如果请求中止,停止处理Flask路由

2024-03-28 09:41:41 发布

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

我有一个flask REST端点,它执行一些cpu密集型的图像处理,需要几秒钟才能返回。通常,这个端点会被调用,然后被客户端中止。在这种情况下,我想取消处理。我怎么能在烧瓶里做这个?

在node.js中,我将执行以下操作:

req.on('close', function(){
  //some handler
});

我希望flask有类似的东西,或者同步方法(request.I s closed()),我可以在处理过程中的某些点进行检查,如果它关闭了,就返回,但找不到。

我想发送一些东西来测试连接是否仍处于打开状态,并在连接失败时捕获异常,但Flask似乎缓冲了所有输出,因此在处理完成并尝试返回结果之前不会引发异常:

An established connection was aborted by the software in your host machine

如果客户端中止请求,我如何在中途取消处理?


Tags: restnode客户端flaskclose烧瓶onjs
3条回答

有一个潜在的。。。你的问题的拙劣的解决办法。Flask has the ability to stream content back to the user via a generator。黑客的部分是将空白数据流作为检查,看看连接是否仍然打开,然后当你的内容完成,生成器可以产生实际的图像。生成器可以检查处理是否完成,如果没有完成,则返回None""或其他内容。

from flask import Response

@app.route('/image')
def generate_large_image():
    def generate():
        while True:
            if not processing_finished():
                yield ""
            else:
                yield get_image()
    return Response(generate(), mimetype='image/jpeg')

我不知道如果客户端关闭连接,会有什么异常,但我敢打赌它是error: [Errno 32] Broken pipe

我正试图在一个项目中做同样的事情,我发现在我的uWSGI和nginx堆栈中,当客户端的流响应被中断时,发生了以下错误

SIGPIPE: writing to a closed pipe/socket/fd (probably the client disconnected) on request
uwsgi_response_write_body_do(): Broken pipe [core/writer.c line 404] during GET
IOError: write error

我可以用一个普通的tryexcept像下面这样

    try:
        for chunk in iter(process.stdout.readline, ''):
            yield chunk
        process.wait()
    except:
        app.logger.debug('client disconnected, killing process')
        process.terminate()
        process.wait()

这给了我:

  1. 使用Flask的生成器功能即时传输数据
  2. 取消连接时没有僵尸进程

据我所知,您不知道在执行期间客户端是否关闭了连接,因为服务器在执行期间没有测试连接是否打开。我知道您可以在Flask应用程序中创建自定义的request_handler,以检测在处理请求后连接是否“断开”。

例如:

from flask import Flask
from time import sleep
from werkzeug.serving import WSGIRequestHandler


app = Flask(__name__)


class CustomRequestHandler(WSGIRequestHandler):

    def connection_dropped(self, error, environ=None):
        print 'dropped, but it is called at the end of the execution :('


@app.route("/")
def hello():
    for i in xrange(3):
        print i
        sleep(1)
    return "Hello World!"

if __name__ == "__main__":
    app.run(debug=True, request_handler=CustomRequestHandler) 

也许您需要进一步研究,当请求到来时,您的自定义request_handler被创建,您可以在__init__中创建一个线程,该线程每秒检查连接的状态,当它检测到连接已关闭(check this thread)时,停止图像处理。但我觉得这有点复杂:(。

相关问题 更多 >