Python 应用程序退出后,线程为何仍在继续运行?

我们有一个 Python 应用程序,在其运行期间会创建一些线程,然后创建一个新的进程和自己一起运行,最后退出。
在这里插入图片描述

from pprint import pprint
import os
import random
import signal
import sys
import threading
import time

class Name(object):
    def __init__(self, name):
        self.name = name

class CallThreads(threading.Thread):
    def __init__(self, target, *args):
        self.target = target
        self.args = args
        threading.Thread.__init__(self)

    def run (self):
        self.target(*self.args)

def main(args):
    print("Hello, world!")
    letter = random.choice(['A', 'B', 'C', 'D', 'E', 'F'])
    count = 0
    while count<3:
        count += 1
        name = Name(letter+str(count))
        t = CallThreads(provider_query, name)
        t.daemon = True
        t.start()
        time.sleep(3)
        print("------------")

    print("Time to die!")
    os.system('python restart.py')
    sys.exit(0)

def provider_query(name):
    while name.name!='':
        print(name.name)
        time.sleep(1)

def signal_handler(signal, frame):
    sys.exit()

if __name__ == '__main__':
    signal.signal(signal.SIGINT, signal_handler)
    main(sys.argv)

我们期望在进程退出后,与它关联的线程将停止运行。然而,在 Kubuntu Linux 上运行上述程序后发现,即使应用程序已经退出并生成了一个新进程,这些进程仍然继续运行。我们可以看到这些线程仍然在向标准输出打印信息。即使将守护进程行注释掉,这些进程仍然继续运行。

为什么在调用 sys.exit() 之后,这些进程仍然继续运行?如何让它们停止?

2、解决方案

问题在于我们永远无法到达 sys.exit() 调用。os.system(‘python restart.py’) 会阻塞,直到 restart.py 完成。但这个子进程 restart.py 在另一个子进程 restart.py 上阻塞,以此类推,直到进程表最终爆掉。在进程表中大约每 9 秒就会看到另一个 restart.py。

为了解决这个问题,我们需要使用 fork() 创建一个子进程来重启应用程序,而不是使用 os.system(‘python restart.py’)。这将允许父进程在子进程启动后立即退出,并且子进程将继续运行应用程序。

修改后的代码如下:

from pprint import pprint
import os
import random
import signal
import sys
import threading
import time

class Name(object):
    def __init__(self, name):
        self.name = name

class CallThreads(threading.Thread):
    def __init__(self, target, *args):
        self.target = target
        self.args = args
        threading.Thread.__init__(self)

    def run (self):
        self.target(*self.args)

def main(args):
    print("Hello, world!")
    letter = random.choice(['A', 'B', 'C', 'D', 'E', 'F'])
    count = 0
    while count<3:
        count += 1
        name = Name(letter+str(count))
        t = CallThreads(provider_query, name)
        t.daemon = True
        t.start()
        time.sleep(3)
        print("------------")

    print("Time to die!")
    # 使用 fork() 创建子进程来重启应用程序
    pid = os.fork()
    if pid == 0:
        # 子进程重新运行应用程序
        os.execvp('python', ['python', 'restart.py'])
    else:
        # 父进程退出
        sys.exit(0)

def provider_query(name):
    while name.name!='':
        print(name.name)
        time.sleep(1)

def signal_handler(signal, frame):
    sys.exit()

if __name__ == '__main__':
    signal.signal(signal.SIGINT, signal_handler)
    main(sys.argv)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值