如果需要,如何正确、干净地终止 python 程序? sys.exit()
不能可靠地执行此功能,因为它只是终止调用它的线程,exit()
和 quit()
不应在终端窗口中使用,raise SystemExit
与 sys.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/