问题描述
class EndProcess(object):
$这个虚拟类与我目前的一个项目类似: b $ b def __init __(self):
self._Q = multiprocessing.Queue()
self.p1 = multiprocessing.Process(target = self.worker,args =(p1 ,))
self.p2 = multiprocessing.Process(target = self.worker,args =(p2,))
self.p3 = multiprocessing.Process(target = self.worker,args = (p3))
self.p1.start()
self.p2.start()
self.p3.start()
def worker(self,name):
while True:
rnd = random.randint(0,100)
self._Q.put((name,rnd))
print(name,rnd)
time.sleep(1)
def __del __(self):
#log队列的最终状态
而不是self._Q.empty():
print(self._Q.get())
#免费资源
...
#清理wo rkers
self.p1.terminate()
self.p2.terminate()
self.p3.terminate()
if __name__ == __main__:
ep = EndProcess()
问题在于<$ c $因为 __ del __
仅在Python的垃圾收集器被引用时才会被调用,特别是在重要的时间点。
如何确保资源始终可以自由设置并且工作人员总是终止?
如何确保资源始终可以自由设置并且工作人员总是被终止?
您可以通过实施上下文管理器方法来实现这一点和。然后,您可以使用 EndProcess
类,并将上下文管理器语句与
一起使用。这样,即使发生错误,您的清理逻辑也会执行:
class EndProcess(object):
def __init __(self):
self._Q = multiprocessing.Queue()
self.p1 = multiprocessing.Process(target = self.worker,args =(p1,))
self.p2 = multiprocessing.Process(target = self.worker,args =(p2,))
self.p3 = multiprocessing.Process(target = self.worker,args =(p3,))
self.p1.start()
self.p2.start()
self.p3.start()
def worker(self,name):
而真:
rnd = random.randint(0,100)
self._Q.put((name,rnd))
print(name,rnd)
time.sleep(1)
def __enter __(self):
#在此处添加您的设置逻辑。初始化任何数据结构。
#设置任何线程等
pass
$ b $ def __exit __(self,exc_type,exc_value,traceback):
#__exit__`的三个参数描述异常
#导致`with`语句执行失败。如果`with`
#语句在没有引发异常的情况下结束,则这些
#参数将为`None`。
#
#这些参数可能对日志记录或
#调试等有用。
而不是self._Q.empty():
print(self._Q.get())
...
self.p1.terminate()
self.p2.terminate()
self.p3.terminate()
...
现在,您可以在上下文管理器语句中使用 EndProcess
实例:
end_process = EndProcess()
...
with end_process as ep:
#像通常一样使用ep。 `__enter__`和`__exit__`将自动为
#。
传递
This dummy class is similar to a current project of mine:
class EndProcess(object):
def __init__(self):
self._Q = multiprocessing.Queue()
self.p1 = multiprocessing.Process(target=self.worker, args=("p1",))
self.p2 = multiprocessing.Process(target=self.worker, args=("p2",))
self.p3 = multiprocessing.Process(target=self.worker, args=("p3",))
self.p1.start()
self.p2.start()
self.p3.start()
def worker(self, name):
while True:
rnd = random.randint(0, 100)
self._Q.put((name, rnd))
print(name, rnd)
time.sleep(1)
def __del__(self):
# "log" final state of Queue
while not self._Q.empty():
print(self._Q.get())
# free resources
...
# clean up workers
self.p1.terminate()
self.p2.terminate()
self.p3.terminate()
if __name__ == "__main__":
ep = EndProcess()
The problem is that __del__
is not guaranteed to be always called, especially at important points in time, since __del__
is only called by Python's garbage collector when the reference count of the object reaches zero.
How can I assure that resources always get set free and the workers always get terminated?
You can accomplish this by implementing the context manager methods __enter__
and __exit__
. You can then use your EndProcess
class with the context manger statement with
. This way, your clean-up logic will executed even if an error occurs:
class EndProcess(object):
def __init__(self):
self._Q = multiprocessing.Queue()
self.p1 = multiprocessing.Process(target=self.worker, args=("p1",))
self.p2 = multiprocessing.Process(target=self.worker, args=("p2",))
self.p3 = multiprocessing.Process(target=self.worker, args=("p3",))
self.p1.start()
self.p2.start()
self.p3.start()
def worker(self, name):
while True:
rnd = random.randint(0, 100)
self._Q.put((name, rnd))
print(name, rnd)
time.sleep(1)
def __enter__(self):
# Add your setup logic here. Initialize any data structures.
# set any threads, etc.
pass
def __exit__(self, exc_type, exc_value, traceback):
# The three arguments to `__exit__` describe the exception
# caused the `with` statement execution to fail. If the `with`
# statement finishes without an exception being raised, these
# arguments will be `None`.
#
# These arguments may be useful for things such as logging, or
# debugging.
while not self._Q.empty():
print(self._Q.get())
...
self.p1.terminate()
self.p2.terminate()
self.p3.terminate()
...
Now you can use EndProcess
instances in a context manager statement:
end_process = EndProcess()
...
with end_process as ep:
# Use ep like you would normally. `__enter__` and `__exit__` will be
# automatically.
pass
这篇关于最终结果和__del__的替代方案杀死一个班的流程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!