RuntimeError: 解释器关闭时无法创建新线程问题求助
问题:点击Reload按钮触发
RuntimeError: can't create new thread at interpreter shutdown 在VSCode运行Python程序时,启动阶段客户端和站点加载正常,但点击加载完成后出现的「Reload clients」按钮重新加载客户端时,触发上述错误。同款程序在朋友的相同设备上可正常运行。
相关代码
import tkinter from tkinter import ttk import threading import time class Main: def __init__(self) -> None: # Variables to check if the progress bar is running (not crucial for the current issue) self.is_progress_bar_running = False self.is_change = False self.state = None self.client_loaded = False # Launching everything in parallel thread_client_list = threading.Thread(target=self.client_list) thread_client_list.start() thread_get_sites = threading.Thread(target=self.get_sites) thread_get_sites.start() tkinter_start = threading.Thread(target=self.show_gui) tkinter_start.start() def client_list(self): """Find clients """ time.sleep(3) self.client_loaded = True return def get_sites(self): """Find sites """ time.sleep(3) return def start_progress_bar(self, direction): """Starts the loading bar until everything is loaded Args: direction (bool): True if the bar is moving to the right, False if the bar is moving to the left """ if not self.is_progress_bar_running: self.is_progress_bar_running = True # If self.client_loaded if not isinstance(self.client_loading, ttk.Progressbar): self.state = None self.is_change = False self.client_loading_label["text"] = "Loading clients in progress..." self.client_loading.destroy() self.client_loading = ttk.Progressbar(self.general_info_frame, orient="horizontal", length=100, mode="indeterminate", takefocus=True, maximum=100, value=0) self.client_loading.grid(row=1,column=1,padx=20,pady=20) self.client_loaded = False # Restart loading clients and sites self.thread_client_list = threading.Thread(target=self.client_list) self.thread_client_list.start() self.thread_get_sites = threading.Thread(target=self.get_sites) self.thread_get_sites.start() # If direction is True, move forward if direction: self.client_loading['value'] += 25 # Change direction when reaching the end if self.client_loading['value'] + 25 > 100: direction = False # Destroy the loading bar when everything is loaded if self.client_loaded: if self.state == 3: self.client_loading_label["text"] = "Error: no internet connection\nReload?" self.client_loading.destroy() self.client_loading = tkinter.Button(self.general_info_frame, text="Reload clients", command= lambda: self.start_progress_bar(True)) self.client_loading.grid(row=1,column=1,padx=20,pady=20) self.is_progress_bar_running = False else: self.client_loading_label["text"] = "Clients loaded!\nReload?" self.client_loading.destroy() self.client_loading = tkinter.Button(self.general_info_frame, text="Reload clients", command= lambda: self.start_progress_bar(True)) self.client_loading.grid(row=1,column=1,padx=20,pady=20) self.is_progress_bar_running = False # Otherwise, start again else: self.is_progress_bar_running = False self.window.after(400, lambda: self.start_progress_bar(direction)) # Otherwise, move backward else: self.client_loading['value'] -= 25 # Change direction when reaching the end if self.client_loading['value'] - 25 < 0: direction = True # Destroy the loading bar when everything is loaded if self.client_loaded: self.client_loading_label["text"] = "Clients loaded!\nReload?" self.client_loading.destroy() self.client_loading = tkinter.Button(self.general_info_frame, text="Reload clients", command= lambda: self.start_progress_bar(True)) self.client_loading.grid(row=1,column=1,padx=20,pady=20) self.is_progress_bar_running = False # Otherwise, start again else: self.is_progress_bar_running = False self.window.after(400, lambda: self.start_progress_bar(direction)) def show_gui(self): """Function that displays the entire interface """ self.window = tkinter.Tk() self.window.title("Synchroteam Task Creation Form") self.frame = tkinter.Frame(self.window) self.frame.pack() # User information self.general_info_frame = tkinter.LabelFrame(self.frame, text="General Information") self.general_info_frame.grid(row=0,column=0,padx=20,pady=20) # Client loading bar self.client_loading_label = tkinter.Label(self.general_info_frame, text="Loading clients in progress...") self.client_loading_label.grid(row=0, column=0) self.client_loading = ttk.Progressbar(self.general_info_frame, orient="horizontal", length=100, mode="indeterminate", takefocus=True, maximum=100, value=0) self.client_loading.grid(row=1,column=0,padx=20,pady=20) for widget in self.general_info_frame.winfo_children(): widget.grid_configure(padx=10, pady=5) if not self.client_loaded: # Start the loading bar until everything is loaded self.window.after(400, lambda: self.start_progress_bar(True)) # Start the loop self.window.mainloop() if __name__ == "__main__": main = Main()
报错信息
Exception in Tkinter callback Traceback (most recent call last): File "C:\Users\Utilisateur\AppData\Local\Programs\Python\Python312\Lib\tkinter\__init__.py", line 1962, in __call__ return self.func(*args) ^^^^^^^^^^^^^^^^ File "c:\Users\Utilisateur\Documents\Batitech\API\test.py", line 97, in <lambda> self.client_loading = tkinter.Button(self.general_info_frame, text="Reload clients", command= lambda: self.start_progress_bar(True)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "c:\Users\Utilisateur\Documents\Batitech\API\test.py", line 59, in start_progress_bar self.thread_client_list.start() File "C:\Users\Utilisateur\AppData\Local\Programs\Python\Python312\Lib\threading.py", line 992, in start _start_new_thread(self._bootstrap, ()) RuntimeError: can't create new thread at interpreter shutdown
原因分析
问题出在主线程生命周期上:__main__中创建Main实例后,主线程会立即执行完毕并进入退出流程,此时Python解释器启动shutdown机制。尽管GUI线程还在运行(mainloop未结束),但解释器已处于关闭阶段,无法再创建新线程,点击Reload按钮时就会触发错误。
朋友设备能正常运行可能是Python版本或环境的细微差异,但代码本身存在主线程提前退出的问题。
修复方法
1. 让主线程等待GUI线程结束
修改__init__方法,将GUI线程保存为实例变量,然后在__main__中调用join()等待它完成,避免主线程提前退出:
def __init__(self) -> None: # ... 其他代码保持不变 ... # 保存GUI线程为实例变量 self.tkinter_start = threading.Thread(target=self.show_gui) self.tkinter_start.start()
if __name__ == "__main__": main = Main() # 等待GUI线程结束后主线程再退出 main.tkinter_start.join()
2. 给后台线程设置守护属性
在start_progress_bar中创建新线程时,设置daemon=True,避免后台线程阻止程序正常退出:
# Restart loading clients and sites self.thread_client_list = threading.Thread(target=self.client_list, daemon=True) self.thread_client_list.start() self.thread_get_sites = threading.Thread(target=self.get_sites, daemon=True) self.thread_get_sites.start()
修改后,主线程会一直等待GUI线程结束,解释器不会提前进入shutdown状态,点击Reload按钮时就能正常创建新线程。
内容的提问来源于stack exchange,提问作者TooFu
相关产品推荐
相关产品推荐

