You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Mac平台使用Tkinter触发'interrupted by signal 11: SIGSEGV'错误求助

问题描述

登录成功进入任务管理器后,点击“添加任务”“查看我的任务”“查看全部任务”“删除任务”“清空全部”“退出登录”任一选项时,十次中有九次会出现interrupted by signal 11: SIGSEGV错误,该如何排查原因?

相关代码
import tkinter as tk
from tkinter import messagebox


class LoginWindow:
    def __init__(self, master):
        self.master = master  # 父窗口
        self.master.title("登录界面")
        self.master.geometry('800x500')

        # 设置背景色
        self.master.configure(bg="turquoise")

        # 创建用户名标签和输入框
        self.username_label = tk.Label(self.master, text="用户名:", bg="turquoise", font=('Arial', 19))
        self.username_label.pack(padx=10, pady=5)
        self.username_entry = tk.Entry(self.master)
        self.username_entry.pack(padx=10, pady=5)

        # 创建密码标签和输入框
        self.password_label = tk.Label(self.master, text="密码:", bg="turquoise", font=('Arial', 19))
        self.password_label.pack(padx=10, pady=5)
        self.password_entry = tk.Entry(self.master, show="*")
        self.password_entry.pack(padx=10, pady=5)

        # 创建登录按钮
        self.login_button = tk.Button(self.master, text="登录", command=self.login, font=('Arial', 19, 'bold'))
        self.login_button.pack(padx=10, pady=25)

        # 存储用户名和密码的字典
        self.users = {
            "admin": "password",
            "user1": "pass1",
            "user2": "pass2"
        }

    def login(self):
        username = self.username_entry.get()  # 获取用户输入
        password = self.password_entry.get()

        # 验证用户名密码
        if username in self.users and self.users[username] == password:
            self.master.destroy()  # 关闭登录窗口
            TaskManagerWindow(username)  # 打开任务管理器窗口
        else:
            messagebox.showerror("登录失败", "用户名或密码错误,请重试。")


class TaskManagerWindow:
    def __init__(self, username):
        self.username = username

        self.master = tk.Tk()  # 根窗口
        self.master.title("任务管理器")

        # 设置背景色
        self.master.configure(bg="light green")

        # 创建任务列表
        self.task_list = tk.Listbox(self.master, width=50)

        self.task_list.grid(row=0, column=0, padx=10, pady=10, columnspan=6, rowspan=4)

        # 创建任务输入框
        self.task_entry = tk.Entry(self.master)
        self.task_entry.grid(row=5, column=0, padx=30, pady=5)
        self.task_entry.insert(tk.END, "Task...")
        self.task_entry.bind("<FocusIn>", self.clear_entry)

        # 创建归属用户输入框
        self.username_entry = tk.Entry(self.master)
        self.username_entry.grid(row=5, column=1, padx=0, pady=5)
        self.username_entry.insert(tk.END, "Attributed to...")
        self.username_entry.bind("<FocusIn>", self.clear_username_entry)

        # 创建添加按钮
        self.add_button = tk.Button(self.master, text="添加任务", command=self.add_task, fg="orchid4")
        self.add_button.grid(row=0, column=7, padx=5, sticky="se")

        # 创建查看我的任务按钮
        self.view_mine_button = tk.Button(self.master, text="查看我的任务", command=self.view_mine, fg="DeepSkyBlue2")
        self.view_mine_button.grid(row=1, column=7, padx=5, sticky="e")

        # 创建查看全部任务按钮
        self.view_all_button = tk.Button(self.master, text="查看全部任务", command=self.view_all, fg="DeepSkyBlue2")
        self.view_all_button.grid(row=1, column=8, padx=5, sticky="w")

        # 创建删除任务按钮
        self.delete_button = tk.Button(self.master, text="删除任务", command=self.delete_task, fg="red4")
        self.delete_button.grid(row=2, column=7, padx=5, sticky="ne")

        # 创建清空全部按钮
        self.clear_button = tk.Button(self.master, text="清空全部", command=self.clear_tasks, fg="red4")
        self.clear_button.grid(row=2, column=8, padx=5, pady=5, sticky="nw")

        # 创建退出登录按钮
        self.logout_button = tk.Button(self.master, text="退出登录", command=self.logout)
        self.logout_button.grid(row=5, column=8, padx=5, pady=5, sticky="w")

        # 存储任务的列表
        self.tasks = []

    def add_task(self):
        task = self.task_entry.get()
        username = self.username_entry.get()
        if task and task != "type..." and username and username != "username...":
            self.tasks.append({"task": task, "user": username})
            self.task_list.insert(tk.END, task)
            self.task_entry.delete(0, tk.END)
            self.task_entry.insert(tk.END, "Task...")
            self.username_entry.delete(0, tk.END)
            self.username_entry.insert(tk.END, "Attributed to...")
        else:
            messagebox.showwarning("任务管理器", "请输入任务和归属用户。")

    def delete_task(self):
        selected_indices = self.task_list.curselection()
        if selected_indices:
            # 倒序遍历选中索引,避免删除时索引偏移
            for index in reversed(selected_indices):
                self.task_list.delete(index)
                del self.tasks[index]
        else:
            messagebox.showwarning("任务管理器", "请选择要删除的任务。")

    def clear_tasks(self):
        confirmed = messagebox.askyesno("任务管理器", "确定要清空所有任务吗?")
        if confirmed:
            self.task_list.delete(0, tk.END)
            self.tasks = []

    def clear_entry(self, event):
        current_value = self.task_entry.get()
        if current_value == "Task...":
            self.task_entry.delete(0, tk.END)

    def clear_username_entry(self, event):
        current_value = self.username_entry.get()
        if current_value == "Attributed to...":
            self.username_entry.delete(0, tk.END)

    def view_mine(self):
        self.task_list.delete(0, tk.END)
        for task in self.tasks:
            if task['user'] == self.username:
                self.task_list.insert(tk.END, task['task'])

    def view_all(self):
        self.task_list.delete(0, tk.END)
        for task in self.tasks:
            self.task_list.insert(tk.END, task['task'])

    def logout(self):
        confirmed = messagebox.askyesno("任务管理器", "确定要退出登录吗?")
        if confirmed:
            self.master.destroy()  # 关闭任务管理器窗口
            root = tk.Tk()
            LoginWindow(root)
            root.mainloop()

    def run(self):
        self.master.mainloop()


def main():
    root = tk.Tk()
    LoginWindow(root)
    root.mainloop()


if __name__ == "__main__":
    main()
排查与修复方案
  • 修复多窗口创建逻辑(核心问题):tkinter不允许同时存在多个tk.Tk()实例,这会导致内部GUI资源冲突,大概率是触发段错误的原因。原代码登录时销毁主窗口、任务管理器新建Tk(),退出登录又重复创建Tk(),完全违背tkinter的窗口管理规范。
    修正方式:

    1. 登录时隐藏原窗口而非销毁,用Toplevel()创建任务管理器子窗口
    2. 退出登录时销毁子窗口,重新显示原登录窗口
      关键代码修改:
    # LoginWindow的login方法
    def login(self):
        username = self.username_entry.get()
        password = self.password_entry.get()
        if username in self.users and self.users[username] == password:
            self.master.withdraw()  # 隐藏登录窗口
            app = TaskManagerWindow(self.master, username)  # 传递原父窗口
            app.run()
    
    # TaskManagerWindow的初始化方法
    def __init__(self, parent, username):
        self.parent = parent
        self.username = username
        self.master = tk.Toplevel(parent)  # 创建子窗口
        self.master.title("任务管理器")
        # 其余代码不变
    
    # TaskManagerWindow的logout方法
    def logout(self):
        confirmed = messagebox.askyesno("任务管理器", "确定要退出登录吗?")
        if confirmed:
            self.master.destroy()
            self.parent.deiconify()  # 重新显示登录窗口
    
  • 修正条件判断不一致问题:add_task方法里判断task != "type...",但输入框默认提示是"Task...",这会导致正常输入的任务被误拦截,虽然不直接引发段错误,但可能触发异常间接影响程序稳定性,改成task != "Task..."即可。

  • 用调试工具定位底层问题:如果修复后仍有段错误,在Linux/macOS下可以用gdb调试:

    gdb python
    (gdb) run your_script.py
    # 触发错误后输入bt查看调用栈
    (gdb) bt
    

    Windows下可以用Visual Studio附加到Python进程,捕获段错误的调用栈,确定是tkinter哪个底层函数出问题。

  • 升级Python和tkinter版本:老旧版本的tkinter存在已知的段错误bug,升级到Python 3.10及以上的稳定版,能解决不少底层兼容性问题。

内容的提问来源于stack exchange,提问作者user22231632

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 21:55:55