确定Python是否正在退出

6

有没有一种方法可以确定Python是否正在关闭?

基本上:

def Foo(object):
  def __del__(self):
    if PYTHON_IS_EXITING:
      do_this
    else:
      do_that

foo1 = Foo()
del foo1 # calls do_that
foo2 # calls do_this when python exits

这里的上下文是当Python退出时,multiprocessing.ThreadPool不起作用,而do_that将并行执行,而do_this将按顺序执行。

谢谢。

3个回答

4
您可以尝试使用atexit
import atexit

def stufftodowhenpythonquits():
    # do some stuff

atexit.register(stufftodowhenpythonquits)

1

在亚当·斯密所说的基础上...

如果您安排atexit来拆除对象,那么很有可能您不需要做任何不同的事情。因为当atexit运行其注册的函数时,您想要执行某些操作的ThreadPool尚未被拆除。因此,atexit注册的函数可以(可能)完全执行析构函数在退出之前调用的内容。

但是,请等一下,还有更多内容。

考虑以下稍微不太明智的尝试来处理对象在退出之前与在退出时的拆除:

#!/usr/bin/python3

import atexit

class Foo:
    def __init__(self):
        self.dead = False
        atexit.register(self.atexit)

    def __del__(self):
        print("%s: in destructor, self.dead is %s"%(id(self), self.dead))
        if not self.dead: self.atexit()

    def atexit(self):
        print("%s: in atexit"%id(self))
        self.dead = True
        atexit.unregister(self.atexit)
        # Do whatever end-of-life processing you need here.  Whether
        # we got here from our destructor or the atexit modules
        # processing, whatever resources we need should (probably)
        # still be available.

foo1 = Foo()
foo2 = Foo()

print("foo1: %s, foo2: %s"%(id(foo1), id(foo2)))
del foo1

如果你运行这个代码,你会发现两个对象的atexit()方法在析构函数被调用时都已经被调用了。这是因为,由于对象的atexit()方法已经注册到了atexit模块,atexit模块持有对该对象的引用。所以即使在del之后,对象仍然存在直到退出。
如果你不需要快速垃圾收集,那么这可能没问题。(在这种情况下,你可以删除self.dead标志和析构函数。因为析构函数永远不会在atexit调用对象的拆卸之前被调用,所以当析构函数被调用时总是没有剩余任务要执行。)
如果你确实需要对象在退出之前消失——那么解决这个问题留给读者作为练习。 :-)

0

在@Phil所说的基础上:

如果您确实需要在退出之前将对象释放

那么这就是标准解决方案:

import atexit


PYTHON_EXITING = False


def _exit():
    print("SETTING PYTHON AT EXIT")
    global PYTHON_EXITING
    PYTHON_EXITING = True


atexit.register(_exit)


class DummyThread:
    def __init__(self, name) -> None:
        self.name = name

    def __del__(self):
        if PYTHON_EXITING:
            print("PYTHON AT EXIT")
        print("__del__", self.name)


foo1 = DummyThread("1")
foo2 = DummyThread("2")

del foo1

输出:

__del__ 1
SETTING PYTHON AT EXIT
PYTHON AT EXIT
__del__ 2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接