Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
719 views
in Technique[技术] by (71.8m points)

multithreading - Is sys.exit(0) a valid way to exit/kill a thread in python?

I'm writing a timer in python. When the timer reaches 0, I want the thread I made to automatically exit.

class Rollgame:
    timer = 0
    def timerf(self, timer):
        self.timer = timer
        while self.timer > 0:
            time.sleep(0.1)
            self.timer -= 0.1
        sys.exit(0)

Is this a valid way to exit a thread? It seems to be working in the context of the program im building, however I'm not sure if it's a good way to do it. If I ever choose to implement this in something like a flask/django app, will this still be valid? Sorry if the question seems stupid or too simple, I've never worked with threading in python before.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

In general, killing threads abruptly is considered a bad programming practice. Killing a thread abruptly might leave a critical resource that must be closed properly, open. But you might want to kill a thread once some specific time period has passed or some interrupt has been generated. There are the various methods by which you can kill a thread in python.

Set/Reset stop flag : In order to kill a threads, we can declare a stop flag and this flag will be check occasionally by the thread. For Example:

# Python program showing 
# how to kill threads 
# using set/reset stop 
# flag 

import threading 
import time 

def run(): 
    while True: 
        print('thread running') 
        global stop_threads 
        if stop_threads: 
            break

stop_threads = False
t1 = threading.Thread(target = run) 
t1.start() 
time.sleep(1) 
stop_threads = True
t1.join() 
print('thread killed') 

In the above code, as soon as the global variable stop_threads is set, the target function run() ends and the thread t1 can be killed by using t1.join(). But one may refrain from using global variable due to certain reasons. For those situations, function objects can be passed to provide a similar functionality as shown below:

# Python program killing 
# threads using stop 
# flag 

import threading 
import time 

def run(stop): 
    while True: 
        print('thread running') 
        if stop(): 
                break
                
def main(): 
        stop_threads = False
        t1 = threading.Thread(target = run, args =(lambda : stop_threads, )) 
        t1.start() 
        time.sleep(1) 
        stop_threads = True
        t1.join() 
        print('thread killed') 
main() 

Using traces to kill threads : This methods works by installing traces in each thread. Each trace terminates itself on the detection of some stimulus or flag, thus instantly killing the associated thread. For Example:

# Python program using 
# traces to kill threads 

import sys 
import trace 
import threading 
import time 
class thread_with_trace(threading.Thread): 
def __init__(self, *args, **keywords): 
    threading.Thread.__init__(self, *args, **keywords) 
    self.killed = False

def start(self): 
    self.__run_backup = self.run 
    self.run = self.__run    
    threading.Thread.start(self) 

def __run(self): 
    sys.settrace(self.globaltrace) 
    self.__run_backup() 
    self.run = self.__run_backup 

def globaltrace(self, frame, event, arg): 
    if event == 'call': 
    return self.localtrace 
    else: 
    return None

def localtrace(self, frame, event, arg): 
    if self.killed: 
    if event == 'line': 
        raise SystemExit() 
    return self.localtrace 

def kill(self): 
    self.killed = True

def func(): 
while True: 
    print('thread running') 

t1 = thread_with_trace(target = func) 
t1.start() 
time.sleep(2) 
t1.kill() 
t1.join() 
if not t1.isAlive(): 
print('thread killed')

In this code, start() is slightly modified to set the system trace function using settrace(). The local trace function is defined such that, whenever the kill flag (killed) of the respective thread is set, a SystemExit exception is raised upon the excution of the next line of code, which end the execution of the target function func. Now the thread can be killed with join().

Finally, Using the multiprocessing module to kill threads : The multiprocessing module of Python allows you to spawn processes in the similar way you spawn threads using the threading module. The interface of the multithreading module is similar to that of the threading module. For Example, in a given code we created three threads(processes) which count from 1 to 9. Now, suppose we wanted to terminate all of the threads. You could use multiprocessing to do that.

# Python program killing 
# a thread using multiprocessing 
# module 

import multiprocessing 
import time 

def func(number): 
    for i in range(1, 10): 
        time.sleep(0.01) 
        print('Processing ' + str(number) + ': prints ' + str(number*i)) 

# list of all processes, so that they can be killed afterwards 
all_processes = [] 

for i in range(0, 3): 
    process = multiprocessing.Process(target=func, args=(i,)) 
    process.start() 
    all_processes.append(process) 

# kill all processes after 0.03s 
time.sleep(0.03) 
for process in all_processes: 
    process.terminate() 

To sum it up, there are many ways to terminate threads, but I peronally wouldn't use sys.exit().


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...