【问题标题】:Why doesn't time.sleep run in parallel in a Tornado coroutine?为什么 time.sleep 不在 Tornado 协程中并行运行?
【发布时间】:2017-10-27 13:19:01
【问题描述】:

当我在一个简单的 Tornado 应用程序中运行此处理程序并使用 curl 向它发出两个请求时,它不会并行运行。当我希望它打印“1 1 2 2 3 3 4 4 5 5”时,它会打印出“1 2 3 4 5 1 2 3 4 5”。

class SleepHandler(RequestHandler):
    def get(self):
        for i in range(5):
            print(i)
            time.sleep(1)

我做错了什么?

【问题讨论】:

    标签: asynchronous tornado


    【解决方案1】:

    原因是time.sleep 是一个阻塞 函数:它不允许控制权返回IOLoop 以便运行其他处理程序。

    当然,time.sleep 在这些示例中通常只是一个占位符,重点是显示当处理程序中的某些内容变慢时会发生什么。无论真正的代码在做什么,要实现并发阻塞代码必须替换为非阻塞等价物。这意味着以下三件事之一:

    • 找到一个对协程友好的等价物。对于 time.sleep,请改用 tornado.gen.sleep:

      class CoroutineSleepHandler(RequestHandler):
          @gen.coroutine
          def get(self):
              for i in range(5):
                  print(i)
                  yield gen.sleep(1)
      

      当此选项可用时,它通常是最好的方法。有关可能有用的异步库的链接,请参阅 Tornado wiki。

    • 查找基于回调的等效项。与第一个选项类似,基于回调的库可用于许多任务,尽管它们使用起来比为协程设计的库稍微复杂一些。这些通常与tornado.gen.Task 一起用作适配器:

      class CoroutineTimeoutHandler(RequestHandler):
          @gen.coroutine
          def get(self):
              io_loop = IOLoop.current()
              for i in range(5):
                  print(i)
                  yield gen.Task(io_loop.add_timeout, io_loop.time() + 1)
      

      同样,Tornado wiki 可用于查找合适的库。

    • 在另一个线程上运行阻塞代码。当异步库不可用时,concurrent.futures.ThreadPoolExecutor 可用于在另一个线程上运行任何阻塞代码。这是一个通用的解决方案,可用于任何阻塞函数,无论是否存在异步对应项:

      executor = concurrent.futures.ThreadPoolExecutor(8)
      
      class ThreadPoolHandler(RequestHandler):
          @gen.coroutine
          def get(self):
              for i in range(5):
                  print(i)
                  yield executor.submit(time.sleep, 1)
      

      请参阅 Tornado 用户指南的 Asynchronous I/O chapter,了解有关阻塞和异步函数的更多信息。

    【讨论】:

    • 我希望你能粘贴这个答案
    • 就是这样。这是从the tornado faq 复制的,因此所有其他提出此问题的问题都可以作为此问题的副本关闭。
    猜你喜欢
    • 2019-12-25
    • 1970-01-01
    • 2013-03-24
    • 2019-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-20
    • 1970-01-01
    相关资源
    最近更新 更多