如何在龙卷风中实现可中断的time.sleep?

时间:2016-07-12 15:48:04

标签: python python-3.x asynchronous concurrency tornado

我正在编写一个进程(称为请求进程),它将定期发送HTTP请求,但可以被另一个线程/进程(称为主进程)中断随时。最初我使用一个线程池来处理带有multiprocessing.Event对象的请求,以便在发送下一个请求之前等待适当的延迟:

# in the main process
poison_pill_event= multiprocessing.Event()

# pass "poison_pill_event" to the requesting process

# in the requesting process which sends requests every wait_interval seconds
poison_pill_event.wait(timeout=time_interval)

这将允许我有一个可中断版本的time.sleep(),以防我需要终止进程。否则,它将允许代码在超时后继续运行。

最近,我发现根据我所需的吞吐量和资源,异步设计是更合适的选择,我尝试过使用Tornado。使用gen.sleep作为非阻塞等待开始,但无法中断。 然后切换到使用Toro.Event's wait function以允许中断。但是,Toro.Event的delay与multiprocessing.Event的timeout不同之处在于它引发了一个Timeout异常,从而中断了执行。另外,我不相信我可以在流程之间分享它,所以我现在尝试将我的主流程与请求流程合并,但这不应该太困难。

所以我的问题是如何重新加入我在龙卷风中对multiprocessing.Event.wait的行为?

1 个答案:

答案 0 :(得分:4)

你不再需要Toro了。 Tornado 4.2及更高版本包含Toro的所有功能。

尝试这样的事情,使用条件而不是事件:

import datetime
import logging

from tornado import gen, options
from tornado.ioloop import IOLoop
from tornado.locks import Condition

condition = Condition()


@gen.coroutine
def waiter():
    for _ in range(10):
        yield condition.wait(timeout=datetime.timedelta(seconds=1))
        logging.info("Tick")


@gen.coroutine
def notifier():
    yield gen.sleep(4.5)
    logging.info("Notify")
    condition.notify()


@gen.coroutine
def runner():
    # Yield two Futures; wait for waiter() and notifier() to finish.
    yield [waiter(), notifier()]


options.parse_command_line()  # Configures logging.
IOLoop.current().run_sync(runner)

您会看到日志输出,如:

[I 160712 12:00:28 foo:15] Tick
[I 160712 12:00:29 foo:15] Tick
[I 160712 12:00:30 foo:15] Tick
[I 160712 12:00:31 foo:15] Tick
[I 160712 12:00:31 foo:21] Notify
[I 160712 12:00:31 foo:15] Tick
[I 160712 12:00:32 foo:15] Tick
[I 160712 12:00:33 foo:15] Tick
[I 160712 12:00:34 foo:15] Tick
[I 160712 12:00:35 foo:15] Tick
[I 160712 12:00:36 foo:15] Tick

请注意,在第二个" Notify"已记录,有两个" Ticks",否则Ticks每秒只发生一次。