【问题标题】:How to implement an interruptible time.sleep in Tornado?如何在 Tornado 中实现可中断的 time.sleep?
【发布时间】:2016-07-12 15:48:04
【问题描述】:

我正在编写一个进程(称为请求进程),它会定期发送 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 不同之处在于它引发了超时异常,因此会停止执行。另外,我不相信我可以在进程之间共享它,所以我现在正在尝试将我的主进程与请求进程合并,但这应该不会太难。

所以我的问题是如何重新模拟我在 Tornado 中使用 multiprocessing.Event.wait 的行为?

【问题讨论】:

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


    【解决方案1】:

    您不再需要 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
    

    请注意,在记录“通知”的那一秒内,有两个“滴答声”,但除此之外,滴答声每秒只发生一次。

    【讨论】:

    • 效果很好!给所有使用这个的人注意:condition.wait 需要一个时间增量。但是,尽管给它一个数值不会引发错误,但它不会以相同的方式工作。似乎将数值视为与IOLoop.time具有相同参考点的绝对时间值。再次感谢@A2J 的帮助。
    猜你喜欢
    • 2011-07-04
    • 1970-01-01
    • 2020-04-13
    • 1970-01-01
    • 2015-07-02
    • 2021-11-23
    • 2017-10-27
    • 1970-01-01
    • 2017-10-09
    相关资源
    最近更新 更多