【发布时间】:2022-12-18 06:38:16
【问题描述】:
我有一个类在它的中启动一个线程__在里面__成员,我想在不再需要该类的实例时加入该线程,所以我在__del__.
结果是__del__当实例的最后一个引用被删除时,永远不会调用成员,但是如果我隐式调用德尔,它被调用。
下面是我的实现的一个较短的修改版本,它显示了这个问题。
import sys
from queue import Queue
from threading import Thread
class Manager:
def __init__(self):
'''
Constructor.
'''
# Queue storing the incoming messages.
self._message_q = Queue()
# Thread de-queuing the messages.
self._message_thread = \
Thread(target=process_messages, args=(self._message_q,))
# Start the processing messages thread to consume the message queue.
self._message_thread.start()
def __del__(self):
'''
Destructor. Terminates and joins the instance's thread.
'''
print("clean-up.")
# Terminate the consumer thread.
# - Signal the thread to stop.
self._message_q.put(None)
# - Join the thread.
self._message_thread.join()
def process_messages( message_q):
'''
Consumes the message queue and passes each message to each registered
observer.
'''
while True:
print("got in the infinite loop")
msg = message_q.get()
print("got a msg")
if msg is None:
# Terminate the thread.
print("exit the loop.")
break
# Do something with message here.
mgr = Manager()
print("mgr ref count:" + str(sys.getrefcount(mgr) - 1)) # -1 cause the ref passed to getrefcount is copied.
#del mgr
控制台为此代码输出以下内容:
mgr ref count:1
got in th infinite loop
由于线程仍在运行,执行挂起。出于某种原因我不明白__del__未被调用,因此线程未终止。
如果我取消注释最后一行 del mgr 以显式删除实例,那么__del__被调用并进行线程清理。
mgr ref count:1
clean-up.
got in the infinite loop
got a msg
exit the loop.
Press any key to continue . . .
有人对此有解释吗?
【问题讨论】:
-
del mgr删除最后一个引用(mgr是一个引用),而不是对象。顺便说一句,在删除引用后,垃圾收集器删除对象之前可能会有延迟。 -
__del__用于资源管理是错误的。而是定义一个上下文管理器。 -
@PavelShishpor
mgr是对该对象的唯一引用。 -
如果您想保证在脚本终止之前执行某些操作,请使用
atexit模块。
标签: python multithreading del