Python(2.7)中的守护线程如何被终止?

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

我希望确保在主线程死亡时,如果一个或多个 do_big_job 线程仍在运行,我不会留下任何临时文件(或僵尸进程),但我也不能简单地设置 daemon=False,因为当主线程退出时,我无法等待它们完成。

1个回答

1

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

然而,关于你问题的第二部分,在官方Python线程文档中docs,对于I/O操作来说,这可能不会很好地发生。

守护线程会在关闭时突然停止。它们的资源(如打开的文件,数据库事务等)可能不会被正确释放。如果你希望你的线程正常停止,请让它们成为非守护线程,并使用适当的信号机制,如Event。

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

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

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

我不确定,但是当主线程以KeyboardInterrupt退出时,我很难让守护线程停止。https://stackoverflow.com/questions/53541455/python-2-daemon-threads-not-getting-killed-on-keyboardinterrupt - Rohit

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