在 Python 的子线程中杀死主线程

107 阅读3分钟

在 Python 中,当函数 check_Temp 退出或引发异常时,我们需要杀死主进程。虽然这种方式可能不是最佳方案,但由于需要集成大量代码,因此这是最简单的方法。我们想要强制关闭程序,即使在关闭程序后出现一些错误也无所谓。

我们尝试了 os.taskskill()、sys.exit()、os.exit() 等方法,但子进程无法杀死主进程。我们不介意所有 Python 进程都被杀死。但是,我们的公司 IT 部门阻止了对 psutil 的下载,因此我们想知道是否有其他解决方案。

以下是代码示例:

import threading
import time
import os
from subprocess import call

def check_Temp(temp, delay, run_event, pid):
    while run_event.is_set():
        ##code for checking temperature will go here.
        time.sleep(delay)
        print("temp is %s \n" % temp)
        temp = temp - 1
        #print os.getpid()
        if temp <= 38:
            raise Exception('LowTemp')
            #call('pkill python', shell=True)
            os.popen('TASKKILL /PID ' + str(pid) + ' /F')
            #os.killall()
            #sys.exit()  #want to exit main loop here

if __name__ == "__main__":
    run_event = threading.Event()
    run_event.set()
    temp = 45
    d1 = .1
    #print os.getpid()
    pid = os.getpid();
    t1 = threading.Thread(target=check_Temp, args=(temp, d1, run_event, pid))
    t1.start()
    print("Starting")

    ########## main code will go here, just have a simple counter here to test the functionality.

    x = 25
    try:
        while 1:
            time.sleep(.1)
            x = x - 1
            print("x is %s \n" % x)
            if x < 0:
                print("x is %s" % x)
                raise Exception('spam', 'eggs')
            #exit()
    except Exception as e:
        print(e)  # the exception instance
        run_event.clear()
        t1.join()
        print("thread successfully closed")

输出结果如下:

Starting
temp is 45

x is 24

temp is 44

x is 23

temp is 43

x is 22

temp is 42

x is 21

temp is 41

x is 20

temp is 40

x is 19

temp is 39

x is 18

Exception in thread Thread-1:
Traceback (most recent call last):
  File "C:\Python26\lib\threading.py", line 532, in __bootstrap_inner
    self.run()
  File "C:\Python26\lib\threading.py", line 484, in run
    self.__target(*self.__args, **self.__kwargs)
  File "C:\PythonSv\multithread6.py", line 14, in check_Temp
    raise Exception('LowTemp')
Exception: LowTemp

x is 17

x is 16

x is 15

x is 14

x is 13

x is 12

x is 11

x is 10

x is 9

x is 8

x is 7

x is 6

x is 5

x is 4

x is 3

x is 2

x is 1

x is 0

x is -1

x is -1
('spam', 'eggs')
thread successfully closed

2、解决方案

问题的关键在于使用标志和回调,而不是异常。

以下是改进后的代码示例:

import threading
import time
import os
from subprocess import call

def check_Temp(temp, delay, run_event, pid, endit):
    while run_event.is_set():
        time.sleep(delay)
        ##code for checking temperature will go here.
        print("temp is %s \n" % temp)
        temp = temp - 1
        #print os.getpid()
        if temp <= 38:
            print('LowTemp %s!' % (temp, ))
            endit()
            run_event.clear()

if __name__ == "__main__":
    run_ok = True

    def Terminator():
        global run_ok
        print("Terminating")
        run_ok = False

    run_event = threading.Event()
    run_event.set()
    temp = 45
    d1 = .1
    #print os.getpid()
    pid = os.getpid();
    run_ok = True
    t1 = threading.Thread(target=check_Temp, args=(temp, d1, run_event, pid, Terminator))
    t1.start()
    print("Starting")

    ########## main code will go here, just have a simple counter here to test the functionality.

    x = 25
    try:
        while run_ok:
            time.sleep(.1)
            x = x - 1
            print("x is %s " % x)
            if x < 0:
                print("x is %s" % x)
                raise Exception('spam', 'eggs')
            #exit()
        t1.join()
        print('Finished!')

使用这种方法,当 temp 等于或低于 38 时,线程将打印一条消息并调用 Terminator() 函数,该函数将清除运行事件并终止主线程。

以下是改进后的代码输出结果:

Starting
temp is 45

x is 24

temp is 44

x is 23

temp is 43

x is 22

temp is 42

x is 21

temp is 41

x is 20

temp is 40

x is 19

temp is 39

x is 18

LowTemp 38 !
Terminating
x is 17

x is 16

x is 15

x is 14

x is 13

x is 12

x is 11

x is 10

x is 9

x is 8

x is 7

x is 6

x is 5

x is 4

x is 3

x is 2

x is 1

x is 0

x is -1

x is -1
('spam', 'eggs')
Finished!

通过使用标志和回调,我们成功地解决了在子线程中杀死主线程的问题。