python - 为什么在 Tornado 服务器 Post 方法中创建线程会出现运行时错误?

标签 python multithreading websocket tornado httpserver

我编写了一个 Tornado HTTP 服务器,并尝试在 API 请求 http://localhost:8889/img 后立即启动一个线程被击中。一段时间后或立即出现 RuntimeError 异常。无法理解这种行为。请解释一下。

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()

最佳答案

我不是并发和 Tornado 方面的专家,但似乎主要问题在于请求对象的生命周期。看,当您将 img 类传递给 tornado.web.Application 时:

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

Tornado 接收对该类的引用,创建其对象并执行正确的方法。当请求完成并且客户端从服务器获得响应时 - 没有什么可做的。一旦请求完成并处于“完成”状态,您就无法写入给客户端,因为这完全没有意义,因为目前客户端对您没有任何期望。

如果您想到 HTTP 设计,就会发现该协议(protocol)就是这样工作的。它不是持续的连接,而是无状态的请求响应通信,有其开始和结束,从另一方面决定了请求的生命周期。

您当然可以在服务器收到请求时启动新线程,例如:

def get(self):
    self.write("Hello, world!")
    tf = threading.Thread(target=self.thread_func)
    tf.start()

def thread_func(self):
    while True:
        print("ok\n")
        time.sleep(0.5)

每次您通过请求到达正确的端点时都会创建新线程,但在请求完成后您无法再真正写入 self

关于python - 为什么在 Tornado 服务器 Post 方法中创建线程会出现运行时错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48596046/

相关文章:

java - 如何获取同一应用程序中运行时单个线程的堆使用情况?

java - Grails 和多线程进程

python - Pandas Dataframe 按列分组

python - 计算数字

python - Python 3.6 中的相互递归类型,使用命名元组语法

node.js websocket 模块已安装但在脚本中不起作用

rest - 是否可以通过 websockets 进行 ReST?

python - np.mean(data.isnull()) 到底是什么?

c - linux 用户级(pthread)线程是否在多个内核上运行?

go - 有什么办法可以防止默认的 golang 程序完成