龙卷风异步队列不等待

时间:2016-03-04 18:55:34

标签: python queue tornado

我用producer& amp;修改了示例队列来自此Tornado https://github.com/spring-projects/spring-integration-java-dsl/issues/59的消费者,但似乎传递给get()的超时参数根本不起作用,因为消费者在抛出异常之前不等待10秒。理想情况下,生产者和消费者将同时运行。另外,我不知道是否以秒或毫秒传递timeout参数:

from tornado import gen
from tornado.ioloop import IOLoop
from tornado.queues import Queue

q = Queue()

@gen.coroutine
def consumer():
    try:
        while True:
            item = yield q.get(timeout=10000)
            try:
                print('Doing work on %s' % item)      
            finally:
                q.task_done()
    except gen.TimeoutError:
        print('timeout')
        return

@gen.coroutine
def producer():
    for item in range(5):
        yield q.put(item)
        print('Put %s' % item)
        yield gen.sleep(2)

@gen.coroutine
def main():
    # Start consumer without waiting (since it never finishes).
    IOLoop.current().spawn_callback(consumer)
    yield producer()     # Wait for producer to put all tasks.
    yield q.join()       # Wait for consumer to finish all tasks.
    print('Done')

IOLoop.current().run_sync(main)

这是执行:

Put 0
Doing work on 0
timeout
Put 1
Put 2
Put 3
Put 4

1 个答案:

答案 0 :(得分:4)

超时

您可以阅读Tornado' Queue.get docs

  

返回一个可在项目可用时解析的Future,或者在超时后引发tornado.gen.TimeoutError。

但这可能会产生误导,因为timeout实际上是deadline。因此必须使用datetime.timedelta object

指定
import datetime
yield q.get(timeout=datetime.timedelta(seconds=1))

或绝对时间:

timeout = 1.5  # in seconds, floats acceptable
deadline = IOLoop.current().time() + timeout
# in most cases IOLoop time is just time.time()
# I've used separate variables only for the notion

yield q.get(timeout=deadline)

Toro中,已合并到Tornado中,此参数称为deadline

在您的代码中,您指定了超时10000,这意味着Thu, 01 Jan 1970 02:46:40 GMT的截止日期。

消费者循环

由于您对整个功能try / except进行了阻止,包括while循环,当TimeoutError发生时,您的消费者就会停止工作。将异常处理移至while循环。

工作示例:

from tornado import gen
from tornado.ioloop import IOLoop
from tornado.queues import Queue

q = Queue()

@gen.coroutine
def consumer():
    i = 0
    while True:
        i += 1
        print('get cycle %s' % i)
        try:
            item = yield q.get(IOLoop.instance().time() + 3)
            try:
                print('Doing work on %s' % item)
            finally:
                q.task_done()
        except gen.TimeoutError:
            print('timeout')

@gen.coroutine
def producer():
    for item in range(5):
        yield q.put(item)
        print('Put %s' % item)
        yield gen.sleep(2)

@gen.coroutine
def main():
    # Start consumer without waiting (since it never finishes).
    IOLoop.current().spawn_callback(consumer)
    yield producer()     # Wait for producer to put all tasks.
    yield q.join()       # Wait for consumer to finish all tasks.
    print('Done')