在哪里加入异步龙卷风请求处理程序中创建的线程?

发布于 2024-11-08 11:54:30 字数 727 浏览 1 评论 0原文

这个让我有点困惑。对 python 中的龙卷风和线程相当陌生,所以我可能完全偏离了我在这里尝试做的事情。

可能最好从一些简化的代码开始:

class Handler(tornado.web.RequestHandler):

  def perform(self):
     #do something cuz hey, we're in a thread!

  def initialize(self):
    self.thread = None

  @tornado.web.asynchronous
  def post(self):

    self.thread = threading.Thread(target=self.perform)
    self.thread.start()

    self.write('In the request')
    self.finish()

  def on_connection_close(self):
    logging.info('In on_connection_close()')
    if self.thread:
      logging.info('Joining thread: %s' % (self.thread.name))
      self.thread.join()

我的问题是 on_connection_close 永远不会被调用,请求得到很好的处理。其次,我以这种方式引入线程是不是做了一些可怕的事情?

This one has me a bit baffled. Fairly new to tornado and threading in python, so I could be completely off the mark with what I'm trying to do here.

Probably best to start with some simplified code:

class Handler(tornado.web.RequestHandler):

  def perform(self):
     #do something cuz hey, we're in a thread!

  def initialize(self):
    self.thread = None

  @tornado.web.asynchronous
  def post(self):

    self.thread = threading.Thread(target=self.perform)
    self.thread.start()

    self.write('In the request')
    self.finish()

  def on_connection_close(self):
    logging.info('In on_connection_close()')
    if self.thread:
      logging.info('Joining thread: %s' % (self.thread.name))
      self.thread.join()

My problem is that on_connection_close is never getting called, requests are getting handled just fine. Secondly, am I doing something terrible introducing threading in this manner?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

剧终人散尽 2024-11-15 11:54:30

我相信 Thread.join() 会阻塞直到线程完成,这可能是您想要避免的事情。您可以让线程回调处理程序,而不是加入。

使用线程时,请注意,tornado 不是线程安全的,因此您不能使用线程中的任何 RequestHandler(例如)方法。

这对我有用:

import functools
import time
import threading
import logging

import tornado.web
import tornado.websocket
import tornado.locale
import tornado.ioloop

class Handler(tornado.web.RequestHandler):
    def perform(self, callback):
        #do something cuz hey, we're in a thread!
        time.sleep(5)
        output = 'foo'
        tornado.ioloop.IOLoop.instance().add_callback(functools.partial(callback, output))

    def initialize(self):
        self.thread = None

    @tornado.web.asynchronous
    def get(self):
        self.thread = threading.Thread(target=self.perform, args=(self.on_callback,))
        self.thread.start()

        self.write('In the request')
        self.flush()

    def on_callback(self, output):
        logging.info('In on_callback()')
        self.write("Thread output: %s" % output)
        self.finish()

application = tornado.web.Application([
    (r"/", Handler),
])

if __name__ == "__main__":
    application.listen(8888)
    tornado.ioloop.IOLoop.instance().start()

您可以使用curl --no-buffer localhost:8888 进行测试。有些浏览器(Safari)似乎要等待连接关闭才能显示任何输出,这让我有一段时间感到困惑。

I believe Thread.join() will block until the thread finishes, probably something you want to avoid. Rather than joining, you can have the thread callback to the handler.

When using threads, be aware that tornado isn't thread-safe, so you can't use any RequestHandler (for example) methods from threads.

This works for me:

import functools
import time
import threading
import logging

import tornado.web
import tornado.websocket
import tornado.locale
import tornado.ioloop

class Handler(tornado.web.RequestHandler):
    def perform(self, callback):
        #do something cuz hey, we're in a thread!
        time.sleep(5)
        output = 'foo'
        tornado.ioloop.IOLoop.instance().add_callback(functools.partial(callback, output))

    def initialize(self):
        self.thread = None

    @tornado.web.asynchronous
    def get(self):
        self.thread = threading.Thread(target=self.perform, args=(self.on_callback,))
        self.thread.start()

        self.write('In the request')
        self.flush()

    def on_callback(self, output):
        logging.info('In on_callback()')
        self.write("Thread output: %s" % output)
        self.finish()

application = tornado.web.Application([
    (r"/", Handler),
])

if __name__ == "__main__":
    application.listen(8888)
    tornado.ioloop.IOLoop.instance().start()

You can test it with curl --no-buffer localhost:8888. Some browsers (Safari) seem to wait for the connection to close before displaying any output, which threw me off for a while.

娜些时光,永不杰束 2024-11-15 11:54:30

AFAIK,仅当客户端终止连接时才会调用 on_connection_close ,这可能可以解释您的问题。
关于线程,我不知道你想做什么,但我不明白为什么你想在 Tornado 请求中创建一个线程,因为 Tornado 的优点之一就是你不必使用线程。
如果我要在您的示例中添加 join ,我会将其放在 self.finish() 之前,但是,您可能可以忽略它......这将取决于你想用线程做什么,但请记住,Tornado 是单线程的,如果在 join() 到来时线程尚未完成,整个过程将被阻塞。

AFAIK, on_connection_close is only called only when the client terminates the connection, which may explain your problem.
Regarding threading, I don't know what you want to do, but I can't see why you would want to create a thread in a Tornado request as one of the advantages of Tornado is exactly that you don't have to use threading.
If I were to add a join to your example I would put it just before self.finish(), however, you can probably just omit it... that will depend on what you want to do with the thread, but remember that Tornado is single-threaded and the whole process will block if the thread is not finished by the time join() comes.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文