最终结果和__del__的替代方案杀死一个班的流程? [英] Alternative to __del__ for final result & killing processes in a class?

查看:160
本文介绍了最终结果和__del__的替代方案杀死一个班的流程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  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的垃圾收集器被引用时才会被调用,特别是在重要的时间点。



如何确保资源始终可以自由设置并且工作人员总是终止?


如何确保资源始终可以自由设置并且工作人员总是被终止?

您可以通过实施上下文管理器方法来实现这一点 __输入__ __ exit __ 。然后,您可以使用 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?

解决方案

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__的替代方案杀死一个班的流程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆