Python中的abortable sleep()

fra*_*ans 8 python thread-sleep

我需要一种sleep()可以中止的方法(如此此处所述).

我的方法是threading.Event.wait()在指定的持续时间内超时:

def abortable_sleep(secs, abort_event):
    abort_event.wait(timeout=secs)
    abort_event.clear()
Run Code Online (Sandbox Code Playgroud)

在调用之后abortable_sleep(10, _abort)我现在可以(从另一个线程)调用_event.set(_abort)让它abortable_sleep()在10秒之前终止.

例:

def sleeping_thread():
    _start = time.perf_counter()
    print("%f thread started" % (time.perf_counter() - _start))
    abortable_sleep(5, _abort)
    print("%f thread stopped" % (time.perf_counter() - _start))

if __name__ == '__main__':

    _abort = threading.Event()
    while True:
        threading.Thread(target=sleeping_thread).start()
        time.sleep(3)
        _abort.set()
        time.sleep(1)
Run Code Online (Sandbox Code Playgroud)

输出:

0.000001 thread started
3.002668 thread stopped
0.000002 thread started
3.003014 thread stopped
0.000001 thread started
3.002928 thread stopped
0.000001 thread started
Run Code Online (Sandbox Code Playgroud)

此代码按预期工作,但我仍然有一些问题:

  • 是不是有一个更简单的方法来获得s.th. 喜欢sleep()什么可以流产?
  • 这可以做得更优雅吗?例如,我必须小心Event未绑定到实例的实例abortable_sleep()
  • 我不得不期待高频循环的性能问题while True: abortable_sleep(0.0001)吗?wait() - 超时是如何实现的?

And*_*zlo 6

我有一个包装类,它基本上在Event. 好消息是你只需要传递一个Sleep对象,sleep()如果你愿意,你可以多次调用它(sleep()虽然不是线程安全的)并且你可以wake()从另一个线程调用。

from threading import Event

class Sleep(object):
    def __init__(self, seconds, immediate=True):
        self.seconds = seconds
        self.event = Event()
        if immediate:
            self.sleep()

    def sleep(self, seconds=None):
        if seconds is None:
            seconds = self.seconds
        self.event.clear()
        self.event.wait(timeout=seconds)

    def wake(self):
        self.event.set()
Run Code Online (Sandbox Code Playgroud)

用法示例:

if __name__ == '__main__':
    from threading import Thread
    import time
    import logging

    logger = logging.getLogger()
    logger.setLevel(logging.DEBUG)
    formatter = logging.Formatter('%(created)d - %(message)s')
    handler = logging.StreamHandler()
    handler.setFormatter(formatter)
    logger.addHandler(handler)

    logger.info("sleep")
    s = Sleep(3)
    logger.info("awake")

    def wake_it(sleeper):
        time.sleep(1)
        logger.info("wakeup!")
        sleeper.wake()

    logger.info("sleeping again")
    s = Sleep(60, immediate=False)
    Thread(target=wake_it, args=[s]).start()
    s.sleep()
    logger.info("awake again")
Run Code Online (Sandbox Code Playgroud)

上面可能会输出如下内容:

1423750549 - sleep
1423750552 - awake
1423750552 - sleeping again
1423750553 - wakeup!
1423750553 - awake again
Run Code Online (Sandbox Code Playgroud)

正是你所做的,但封装在一个类中。