代码之家  ›  专栏  ›  技术社区  ›  Bastian

如何在上下文管理器中使用线程?

  •  4
  • Bastian  · 技术社区  · 7 年前

    考虑一下这个 threading.Thread 类别:

    class Sleeper(threading.Thread):
        def __init__(self, sleep=5.0):
            threading.Thread.__init__(self)
            self.event = threading.Event()
            self.sleep = sleep
    
        def run(self):
            while self.sleep > 0 and not self.event.is_set():
                self.event.wait(1.0)
                self.sleep -= 1
    
        def stop(self):
            self.event.set()
    

    它会休眠一定时间,然后在达到该时间之前退出或停止。

    我将其用作:

    sleeper = Sleeper()
    try:
        sleeper.start()
        # do stuffs here
    except:
        # handle possible exceptions here
    finally:
        sleeper.stop()
    

    我更愿意像使用上下文管理器一样使用它:

    with Sleeper():
        # do stuffs here
    

    然后退出时线程停止 with

    我已尝试添加 __enter__ __exit__ 方法和它似乎有效,但我不确定这是一条路:

    def __enter__(self):
        self.start()
        return self
    

    def __exit__(self, type, value, traceback):
        self.stop()
    

    但我真的不知道我在这里做什么。应该如何正确完成?

    1 回复  |  直到 7 年前
        1
  •  7
  •   Menglong Li    7 年前

    尽管不太理解您的问题,但由于缺乏aws相关问题的背景。正如您所提到的,使用上下文来实现这一点是可行的。

    import threading
    import time
    
    
    class Sleeper(threading.Thread):
        def __init__(self, sleep=5.0):
            threading.Thread.__init__(self, name='Sleeper')
            self.stop_event = threading.Event()
            self.sleep = sleep
    
        def run(self):
            print('Thread {thread} started'.format(thread=threading.current_thread()))
            while self.sleep > 0 and not self.stop_event.is_set():
                time.sleep(1.0)
                self.sleep -= 1
            print('Thread {thread} ended'.format(thread=threading.current_thread()))
    
        def stop(self):
            self.stop_event.set()
    
        def __enter__(self):
            self.start()
            return self
    
        def __exit__(self, *args, **kwargs):
            self.stop()
            print('Force set Thread Sleeper stop_event')
    
    
    with Sleeper(sleep=2.0) as sleeper:
        time.sleep(5)
    
    print('Main Thread ends')
    

    您可以测试以下两种情况:1。主要睡眠时间多,2。睡眠线程有一个更大的睡眠参数,它们将得到两个结果;

    如果您仍然希望与main的Sleeper线程交互,那么您的代码应该如下所示:

    with Sleeper(sleep=2.0) as sleeper:
        cnt = 15
    
        while cnt > 0 and sleeper.is_alive():
            print(cnt)
            cnt -= 1
            time.sleep(1)
    

    你可以看到主屏幕上只打印了几个数字,因为睡眠者已经死了,不再活着了。