python - sys.exit(0) 是退出/终止 python 线程的有效方法吗?

标签 python multithreading oop timer exit

我正在用 python 编写一个计时器。当计时器达到 0 时,我希望我创建的线程自动退出。

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)

这是退出线程的有效方法吗?它似乎在我正在构建的程序的上下文中工作,但是我不确定这是否是一个好方法。 如果我选择在 Flask/django 应用程序中实现这一点,这仍然有效吗? 抱歉,如果这个问题看起来很愚蠢或太简单,我以前从未在 python 中使用过线程。

最佳答案

一般来说,突然终止线程被认为是一种不好的编程习惯。突然终止线程可能会使必须正确关闭的关键资源保持打开状态。但是,一旦经过某个特定时间段或生成某个中断,您可能希望终止线程。您可以通过多种方法来终止 python 中的线程。

设置/重置停止标志: 为了杀死一个线程,我们可以声明一个停止标志,并且线程偶尔会检查该标志。例如:

# 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') 

在上面的代码中,一旦设置了全局变量stop_threads,目标函数run()就会结束,并且可以使用t1.join()杀死线程t1。但由于某些原因,人们可能会避免使用全局变量。对于这些情况,可以传递函数对象来提供类似的功能,如下所示:

# 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() 

使用跟踪来终止线程: 此方法的工作原理是在每个线程中安装跟踪。每个跟踪都会在检测到某些刺激或标志时自行终止,从而立即终止关联的线程。例如:

# 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')

在此代码中,start() 稍作修改,以使用 settrace() 设置系统跟踪函数。本地跟踪函数的定义是,每当设置相应线程的终止标志(killed)时,在执行下一行代码时会引发 SystemExit 异常,从而结束目标函数 func 的执行。现在可以使用 join() 终止线程。

最后,使用多处理模块杀死线程: Python 的多处理模块允许您以与使用 threading 模块生成线程类似的方式生成进程。多线程模块的接口(interface)与线程模块的接口(interface)类似。例如,在给定的代码中,我们创建了三个线程(进程),从 1 计数到 9。现在,假设我们想要终止所有线程。您可以使用多处理来做到这一点。

# 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() 

综上所述,终止线程的方法有很多,但我个人不会使用sys.exit()。

关于python - sys.exit(0) 是退出/终止 python 线程的有效方法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65630708/

相关文章:

python - 如何为多列添加功能?

c - 从 C 中的 main 返回时,正在运行的线程会发生什么?

c# - 在线程之间共享局部变量是否安全(通过回调闭包)?

java - 需要在 Java 中继承 API 的帮助

c# - 我应该使用哪种设计模式来动态地为对象提供不同的效果?

对象引用的 Java 哈希表问题

python - 我应该如何解压 dict 键,值作为列,嵌入式 MySQL 语句中的值?

python - jsonpickle 为 python 对象属性添加前导下划线

python - 如何打印包含另一个列表中所有字符串的子列表?

c# - 来自共享位置的数据的私有(private)副本