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

标签 python python-multithreading contextmanager

考虑这个 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 block 时停止。

我已经尝试添加 __enter____exit__ 方法,它似乎有效,但我不确定这是要走的路:

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

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

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

最佳答案

虽然不太理解您的问题,但由于缺乏与您的 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. main sleep 的时间更长, 2. Sleeper thread 的sleep parameter 更大,最终会出现两种结果;

如果您仍想通过主线程与 Sleeper 线程交互,您的代码应如下所示:

with Sleeper(sleep=2.0) as sleeper:
    cnt = 15

    while cnt > 0 and sleeper.is_alive():
        print(cnt)
        cnt -= 1
        time.sleep(1)

你可以看到 main 只打印了一些数字,因为 sleeper 已经结束并且不再存活了。

关于python - 如何在上下文管理器中使用线程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47915356/

相关文章:

python - 如何在 matplotlib 箱线图中标记四分位数?

python-multithreading - gRPC + Thread 本地问题

python - 上下文管理器定义错误

python - 在 2D numpy 矩阵中查找特定点距离 1 内的所有点

python - Robotframework导入自己的Python库

python - 在 python 中的 os.environ 上使用 copy.deepcopy 似乎坏了

python - 异步队列在与后台线程一起使用时挂起

python - RabbitMQ:消费和发布可以在一个线程中完成吗?

python - SQLAlchemy session 的上下文/范围是否需要非自动对象/属性过期?

Python:在类方法上使用 contextmanager 的意外行为