python - 终止 python 程序的正确方法,无论调用位置如何,并进行清理

标签 python python-3.x exit-code

如果需要,如何正确、干净地终止 python 程序? sys.exit() 不能可靠地执行此功能,因为它只是终止调用它的线程,exit()quit()不应在终端窗口中使用,raise SystemExitsys.exit() 有相同的问题并且是不好的做法,os._exit( ) 立即杀死所有东西并且不清理,这可能会导致残留问题。

有没有办法始终终止程序和所有线程,而不管它是从哪里调用的,同时仍然进行清理?

最佳答案

Is there a way to ALWAYS kill the program and all threads, regardless of where it is called from, while still cleaning up?

否 - “无论从何处调用”和“清理”都不要混用。


既可靠又安全地终止线程根本就没有意义。杀死一个线程(或进程)意味着中断它正在做的事情——包括清理。不中断任何清理意味着,好吧,实际上并没有杀死线程。您不能同时拥有两者。

如果您想杀死所有线程,那么os._exit() 正是您所要求的。如果您想清理线程,没有通用功能可以实现。

关闭线程的唯一可靠方法是实现您自己的安全中断。在某种程度上,这必须根据您的用例进行定制 - 毕竟,您是唯一知道何时可以安全关闭的人。

用异常杀死一个线程

底层的 CPython API 允许您在另一个线程中引发异常。参见示例 this answer .

这不便携且不安全。您可以在任意时间终止该线程。如果您的代码预期出现异常或您的资源自行清理(通过 __del__),您可以限制危害,但不能排除它。不过,它非常接近大多数人认为的“干净利落”。

使用 atexit 的自清洁守护线程

使用 Thread.daemon 运行的线程如果没有其他线程剩余,则突然终止。通常,这是您想要的一半:如果所有适当的线程退出,优雅地终止。

现在,关键是 daemon 线程不会阻止关闭。这也意味着它不会阻止 atexit 运行!因此,守护进程可以使用 atexit 自动关闭自身并在终止时进行清理。

import threading
import atexit
import time


class CleanThread(threading.Thread):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.daemon = True
        # use a signal to inform running code about shutdown
        self.shutdown = threading.Event()

    def atexit_abort(self):
        # signal to the thread to shutdown with the interpreter
        self.shutdown.set()
        # Thread.join in atexit causes interpreter shutdown
        # to be delayed until cleanup is done
        self.join()  # or just release resources and exit

    def run(self):
        atexit.register(self.atexit_abort)
        while not self.shutdown.wait(0.1):
            print('who wants to live forever?')
        print('not me!')
        atexit.unregister(self.atexit_abort)


thread = CleanThread()
thread.start()
time.sleep(0.3)
# program exits here

请注意,这仍然需要您的代码来监听清理信号!根据线程的作用,还有其他机制可以实现这一点。例如,concurrent.future 模块在关闭时清空所有工作线程的任务队列。

关于python - 终止 python 程序的正确方法,无论调用位置如何,并进行清理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49325401/

相关文章:

python - 使用python从opencv级联获取特定的图像横截面

perl - 从 Perl 运行命令时段错误消失

python - 将可变数量的 csv 文件中的一列合并到一个 csv 文件中

python - 导入错误 : No module named http django

Python 根据第一个属性在内部按日期排序

python - Jupyter笔记本: Error while connecting to Server

Python 高效地从 XML 中提取嵌套元素

python-3.x - SVM 回归的调整参数

windows - 进程被强行杀死时的进程退出代码

bash - 启动独立的作业步骤并跟踪最高退出代码