python (2.7) 中的守护线程是如何被杀死的

Dav*_*ave 6 multithreading python-2.7

当主线程退出时,守护线程会发生什么?他们是如何关闭的?有没有办法确保执行清理代码?

这是我遇到的情况的草图:

import os
import subprocess
import threading
import glob
import datetime

def do_big_job(result='result.txt'):
    tmpfile = result+'.tmp'
    err = subprocess.call(['my_time_consuming_script', '-o', tmpfile])
    if err == 0:
        os.rename(tmpfile, result)
    else:
        os.remove(tmpfile) # process failed, clean up temp file



def main():
    not_done = True
    update = 0
    while not_done:

        # we can see if new data are available,
        # and start a process to get/prep it
        if new_data_available():
            args = ('result{0:05}.txt'.format(update),)
            th = threading.Thread(target=do_big_job, args=args)
            update = update + 1
            th.daemon = True 
            th.start()

        # but we don't need/want to wait for that process
        # to complete before continuing to iterate

        currently_available = glob.glob('result*.txt')
        # <snip>
        # rest of loop just uses what is available,
        # we don't want/need to block for updated data
        # to meet other responsiveness requirements
Run Code Online (Sandbox Code Playgroud)

我想确保我不会留下任何临时文件(或僵尸程序),如果在一个(或多个)主线程模躺在附近do_big_job线程仍在运行,但我也不能随便设置daemon=False,因为当主要退出时,我不能等待它们完成。

kin*_*ian 1

当主线程退出时,所有守护线程也会退出。因此,如果您的 main() 退出,所有守护线程也将退出。

然而,来到问题的第二部分,根据 I/O 操作的官方 python 线程文档,这可能不会正常发生。

守护进程线程在关闭时突然停止。它们的资源(例如打开的文件、数据库事务等)可能无法正确释放。如果您希望线程正常停止,请将它们设置为非守护进程并使用合适的信号机制(例如事件)。

因此,如果您想检查周围是否有僵尸线程,可以调用 isAlive() 函数。现在关于如何确保主线程死亡后执行清理代码;我认为这取决于你所说的死亡是什么意思。

如果您指的是脚本的正常退出(例如,KeyboardInterrupt 异常,调用 sys.exit()),那么确实值得看一下 atexit模块,该模块注册在进程终止时要执行的函数。

如果“死亡”意味着 main() 被信号杀死,或者发生 Python 致命内部错误,或者调用 os._exit() ,那么 atexit 模块将无法工作。在这种情况下,我想到的一个可能的解决方案是创建另一个看门狗进程,该进程不断监视您的 main() 并在适当的时候运行清理代码。