Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/315.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 为什么在Tornado RequestHandler中的_init__u;中调用的异步使用者的行为与静态调用的不同?_Python_Asynchronous_Tornado_Consumer - Fatal编程技术网

Python 为什么在Tornado RequestHandler中的_init__u;中调用的异步使用者的行为与静态调用的不同?

Python 为什么在Tornado RequestHandler中的_init__u;中调用的异步使用者的行为与静态调用的不同?,python,asynchronous,tornado,consumer,Python,Asynchronous,Tornado,Consumer,我试图使用Tornado为每个处理程序创建一个具有唯一队列的异步服务器。当调用端点时,作业被放入队列中。我有一个consumer函数,它异步地“消费”队列中的作业。但是,消费者的行为往往会有所不同,这取决于我是将其称为self.consumer()还是asynchHandler.consumer()。我最初的猜测是,这是因为实例级锁定,但找不到证据。我连续发出4个post请求。下面是两个片段及其输出 import tornado.web from tornado import gen from

我试图使用Tornado为每个处理程序创建一个具有唯一队列的异步服务器。当调用端点时,作业被放入队列中。我有一个consumer函数,它异步地“消费”队列中的作业。但是,消费者的行为往往会有所不同,这取决于我是将其称为
self.consumer()
还是
asynchHandler.consumer()
。我最初的猜测是,这是因为实例级锁定,但找不到证据。我连续发出4个post请求。下面是两个片段及其输出

import tornado.web
from tornado import gen
from time import sleep, time
from tornado.queues import Queue
from concurrent.futures import ThreadPoolExecutor
from tornado.ioloop import IOLoop

class AsyncHandler(tornado.web.RequestHandler):

    JOB_QUEUE = Queue()
    EXECUTOR = ThreadPoolExecutor()

    def post(self):
        job = lambda: sleep(3) or print("{}:handler called".format(int(time())))
        self.JOB_QUEUE.put(job)
        self.set_status(200)
        self.finish()

    @staticmethod
    @gen.coroutine
    def consumer():
        while True:
            job = yield AsyncHandler.JOB_QUEUE.get()
            print("qsize : {}".format(AsyncHandler.JOB_QUEUE.qsize()))
            print(AsyncHandler.JOB_QUEUE)
            output = yield AsyncHandler.EXECUTOR.submit(job)
            AsyncHandler.JOB_QUEUE.task_done()


if __name__ == "__main__":
    AsyncHandler.consumer()
    APP = tornado.web.Application([(r"/test", AsyncHandler)])
    APP.listen(9000)
    IOLoop.current().start()
这将给出预期的输出:

qsize : 0
<Queue maxsize=0 tasks=1>
1508618429:handler called
qsize : 2
<Queue maxsize=0 queue=deque([<function...<lambda> at 0x7fbf8f741400>, <function... <lambda> at 0x7fbf8f760ea0>]) tasks=3>
1508618432:handler called
qsize : 1
<Queue maxsize=0 queue=deque([<function AsyncHandler.post.<locals>.<lambda> at 0x7fbf8f760ea0>]) tasks=2>
1508618435:handler called
qsize : 0
<Queue maxsize=0 tasks=1>
1508618438:handler called
输出奇怪(令人愉快)如下所示:

qsize : 0
<Queue maxsize=0 tasks=1>
qsize : 0
<Queue maxsize=0 tasks=2>
qsize : 0
<Queue maxsize=0 tasks=3>
qsize : 0
<Queue maxsize=0 tasks=4>
1508619138:handler called
1508619138:handler called
1508619139:handler called
1508619139:handler called
qsize:0
qsize:0
qsize:0
qsize:0
1508619138:已调用处理程序
1508619138:已调用处理程序
1508619139:已调用处理程序
1508619139:已调用处理程序

请注意,现在我们正在调用consumer inside
\uuuu init\uuuu
。我们可以看到任务以并行方式构建和执行(没有队列构建),几乎同时完成。这就好像
output=yield asynchHandler.EXECUTOR.submit(作业)
不会阻止未来。即使经过多次实验,我也无法解释这种行为。我非常感谢您的帮助。

第一个应用程序只有一个运行的
消费者
,因为它只执行一次。每个请求“阻塞”(每次只有一个是循环)消费者,因此下一个请求将在前一个请求之后处理


后一个应用程序在每个请求中启动一个新的
消费者
循环(因为RequestHandler是根据请求创建的)。因此,第一个请求不会“阻止”下一个请求,因为第一个应用程序只有一个运行的消费者,因为它只执行一次。每个请求“阻塞”(每次只有一个是循环)消费者,因此下一个请求将在前一个请求之后处理


后一个应用程序在每个请求中启动一个新的
消费者
循环(因为RequestHandler是根据请求创建的)。因此,第一个请求不会“阻止”下一个请求,因为有全新的
而True
get
submit

我现在看到了,你提到了它!谢谢我通过打印调用消费者的实例来确认它。所以基本上while-True循环应该只是一个消费者调用。我的理解是,所有请求处理程序都在主线程中执行,因此多个使用者不应该是问题。你能看到这种方法有什么特别的缺点吗?我现在明白了,你提到了!谢谢我通过打印调用消费者的实例来确认它。所以基本上while-True循环应该只是一个消费者调用。我的理解是,所有请求处理程序都在主线程中执行,因此多个使用者不应该是问题。这种方法有什么特别的缺点吗?
qsize : 0
<Queue maxsize=0 tasks=1>
qsize : 0
<Queue maxsize=0 tasks=2>
qsize : 0
<Queue maxsize=0 tasks=3>
qsize : 0
<Queue maxsize=0 tasks=4>
1508619138:handler called
1508619138:handler called
1508619139:handler called
1508619139:handler called