为什么在Python线程中调用sys.exit()不退出?

125 投票
6 回答
104433 浏览
提问于 2025-04-15 11:48

我有点困惑,为什么下面这段代码在线程中调用时不会退出,但在主线程中调用时却会退出。

import sys, time
from threading import Thread

def testexit():
    time.sleep(5)
    sys.exit()
    print "post thread exit"

t = Thread(target = testexit)
t.start()
t.join()
print "pre main exit, post thread exit"
sys.exit()
print "post main exit"

文档里说 sys.exit() 这个调用应该让Python退出。我从这个程序的输出中看到,“线程退出后”的那句话从来没有被打印出来,但主线程在线程调用退出后还是继续运行。

是不是每个线程都创建了一个独立的解释器实例,而调用 exit() 只是退出了那个独立的实例?如果是这样,线程是怎么管理共享资源的访问的呢?如果我真的想从线程中退出程序(虽然我并不想这样,只是为了理解),那该怎么做呢?

6 个回答

27

如果我想从线程中退出程序怎么办?

除了Deestan提到的方法,你还可以使用 os._exit(注意有个下划线)。在使用之前,要确保你明白这个方法不会进行任何清理工作(比如不会调用 __del__ 或类似的东西)。

49

如果我想从线程中退出程序怎么办?

对于Linux系统:

os.kill(os.getpid(), signal.SIGINT)

这段代码会向主线程发送一个叫做SIGINT的信号,这会引发一个KeyboardInterrupt。虽然这个过程比较复杂,但好处是主线程会按照标准的关闭流程进行清理,比如处理线程、网络连接、文件等,最后执行一些收尾代码。此外,你还可以设置一个处理程序,以便在不同情况下做出反应。

对于Windows系统:

上面的做法在Windows上不管用,因为你只能发送一个SIGTERM信号,而这个信号Python并不处理,效果和os._exit()是一样的。

唯一的选择是使用:

os._exit()

这会直接退出整个进程,而不会进行任何清理。如果需要清理,线程就需要通过其他方式与主线程沟通,比如使用队列或者向事件循环发送一个事件。

96

sys.exit() 会引发一个叫做 SystemExit 的异常,thread.exit() 也是如此。所以,当在某个线程里调用 sys.exit() 时,它引发的这个异常和调用 thread.exit() 的效果是一样的,这就是为什么只有那个线程会退出的原因。

撰写回答