我正在通过waitress.serve(app, send_bytes=1)
运行Flask应用。如果客户端关闭连接,我将尝试实现停止长时间运行的SQL查询的功能(例如,按浏览器中的“停止”按钮)。
我遇到了一个完全相同的问题:Stop processing Flask route if request aborted,它建议尝试定期写入连接以查看其是否仍然打开。 (我尝试写0字节甚至更进一步,我试图每秒写一个1字节的字符串“ q”。)但是当我在应用程序中实现它时,它不会产生任何“套接字关闭”或“连接”如果浏览器在等待响应时按下“停止”,则会显示“关闭”错误。
即,预期的行为是客户端每秒收到一次“ q”直到获得完整响应,并且python控制台输出是“从队列中获取”,然后是“连接仍然有效,队列为空”,每秒重复一次,直到按下浏览器中的“停止”按钮并发生某种异常为止(我在这里设置了几个异常处理程序,以在应该显示的位置捕获它)。但是实际的行为是,在单击浏览器中的“停止”按钮后,python控制台将继续每秒输出“从队列中获取”和“连接仍然有效,队列为空”,直到查询完成,然后“线程:置于队列中”和“从队列中获取”被记录。在任何时候都不会抛出套接字/连接错误。
为了进行比较,在node.js(位于同一台Windows计算机上)中,使用express,req.on('close', () => {console.log('connection closed');})
立即检测到浏览器中的“停止”按钮按下。
任何关于为什么这种方式的想法吗?如何检测客户端是否已在Windows的Waitress / Flask中关闭了连接?
query_string = 'xxx'
@app.route('/filter')
def filter_route():
response_from_filter = lambda filter: json.dumps({
...
})
def threaded_query(query_str, queue_obj):
def callable():
try:
filter = db.session.execute(query_string)
queue_obj.put(response_from_filter(filter))
print "thread: put on queue"
except Exception as e:
print e, "thread error"
return callable
def generate(queue_obj):
while True:
try:
print "getting from queue"
result = queue_obj.get(block=True, timeout=1)
print "got from queue"
yield result
return
except GeneratorExit as ge:
print "generator exit"
break
except Queue.Empty as e:
print e, "connection still alive, queue empty"
yield "q"
except Exception as e:
print e, "generic exception"
query_queue = Queue.Queue()
thread = threading.Thread(target=threaded_query(query_string, query_queue))
thread.start()
try:
return Response(stream_with_context(generate(query_queue)))
except Exception as e:
print e, "Response exception"