为什么在 Tornado 服务器 Post 方法中创建线程会导致运行时错误?



我已经编写了一个Tornado HTTP服务器,并试图在API请求 http://localhost:8889/img 被击中后立即启动线程。一段时间后或立即收到运行时错误异常。无法理解此行为。请解释一下。

import tornado.ioloop
import tornado.web
import threading
import time
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world")
class img(tornado.web.RequestHandler):
def post(self):
t_img = threading.Thread(target=self.sendimg,)
t_img.start()
def sendimg(self):
while True:
self.write({"name":"vinay"})
print("sent")
time.sleep(0.5)
def make_app():
return tornado.web.Application([
(r"/", MainHandler),
(r"/img", img),
])
if __name__ == "__main__":
app = make_app()
app = tornado.httpserver.HTTPServer(app)
app.listen(8889)
tornado.ioloop.IOLoop.current().start()

错误:

self.write({"name":"vinay"})
File "/Users/vinaykp/anaconda3/lib/python3.6/site-
packages/tornado/web.py", line 708, in write
raise RuntimeError("Cannot write() after finish()")
RuntimeError: Cannot write() after finish()

我不是并发和龙卷风方面的专家,但似乎主要问题在于请求对象的生命周期。看,当你把img类传给tornado.web.Application

def make_app():
return tornado.web.Application([
(r"/", MainHandler),
(r"/img", img),
])

Tornado 接收对类的引用,创建其对象并执行正确的方法。当请求完成并且客户端从服务器获得响应时 - 这没有什么可做的了。一旦请求完成并处于"完成"状态,您将无法write客户端,因为它完全没有意义,因为目前客户端并不期望您提供任何内容。

如果你想到HTTP设计,那就是这个协议的工作方式。它不是持续的连接,而是无状态的请求-响应通信,它有其开始和结束,另一方面,它决定了请求生命周期。

当然,当您的服务器受到请求命中时,您可以启动新的线程,例如:

def get(self):
self.write("Hello, world!")
tf = threading.Thread(target=self.thread_func)
tf.start()
def thread_func(self):
while True:
print("okn")
time.sleep(0.5)

并且每次您使用请求命中正确的端点时都会创建新的线程,但是在请求完成后,您无法真正写入self

最新更新