gpt4 book ai didi

python - 当另一个线程处于事件状态时,为什么不在全局对象上调用__del__?

转载 作者:行者123 更新时间:2023-12-03 13:07:49 25 4
gpt4 key购买 nike

我正在一个项目,其结构与下面的代码所示类似。我希望有一个对象在创建时打开一个线程,并在该对象被销毁时自动将其关闭。当在函数中实例化对象时,此方法按预期工作,但是在全局范围内创建对象时,未调用__del__,导致程序挂起。

import threading

def thread(event):
event.wait()
print("Terminating thread")

class ThreadManager:
def __init__(self):
self.event = threading.Event()
self.thread = threading.Thread(target=thread, args=(self.event,))
self.thread.start()

def __del__(self):
self.event.set()
print("Event set")
self.thread.join()

if __name__ == '__main__':
print("Creating thread")
manager = ThreadManager()
#del manager

除非我明确删除 manager对象,否则程序将挂起。我假设解释器正在等待删除全局对象,直到所有非守护程序线程都完成为止,从而导致死锁。

我的问题是,是否有人可以确认这一点并提供解决方法(我已经阅读了 this页面,所以我没有在寻找使用 close()函数或类似方法的解决方案,我只是好奇地听到可以执行的替代方案的想法自动清理),否则反驳并告诉我我做错了什么?

最佳答案

与C++之类的语言不同,Python不会在对象超出范围时立即销毁它们,这就是__del__不可靠的原因。您可以在这里阅读有关此内容的更多信息:https://stackoverflow.com/a/35489349/5971137

至于解决方案,我认为这是上下文管理器(with)的完美案例:

>>> import threading
>>>
>>> def thread(event):
... event.wait()
... print("Terminating thread")
...
>>> class ThreadManager:
... def __init__(self):
... print("__init__ executed")
... self.event = threading.Event()
... self.thread = threading.Thread(target=thread, args=(self.event,))
... self.thread.start()
... def __enter__(self):
... print("__enter__ executed")
... return self
... def __exit__(self, *args):
... print("__exit__ executed")
... self.event.set()
... print("Event set")
... self.thread.join()
...
>>> with ThreadManager() as thread_manager:
... print(f"Within context manager, using {thread_manager}")
...
__init__ executed
__enter__ executed
Within context manager, using <__main__.ThreadManager object at 0x1049666d8>
__exit__ executed
Event set
Terminating thread
print语句显示执行顺序按您希望的方式工作,其中 __exit__现在是您可靠的清除方法。

关于python - 当另一个线程处于事件状态时,为什么不在全局对象上调用__del__?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54408266/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com