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

使用Tkinter编写程序保存YAML时出现pickle _tkinter.tkapp对象错误

问题修复:TypeError: cannot pickle '_tkinter.tkapp' object

错误原因

你在saveCfg函数里直接把ttk.Entry控件对象(name和password变量)赋值给了yaml_dict,而YAML序列化时需要将对象转换为可pickle的格式,但tkinter的控件实例无法被pickle,这就是报错的核心原因。另外代码里还有一处循环配置行权重的错误,会导致窗口布局异常。

修复步骤

  • 获取输入文本而非控件对象:调用Entry控件的.get()方法提取用户输入的字符串,而不是直接保存控件本身。
  • 修正窗口行权重配置:原代码中循环配置行权重时,错误地始终使用row作为索引,应该遍历0到row-1的索引。
  • 优化YAML读写的安全性与编码:读写文件时指定编码,避免乱码;加载YAML时明确使用CLoader,保持一致性。

修复后的完整代码

import yaml
import tkinter as tk
from tkinter import ttk

# 加载YAML配置,指定编码并使用CLoader
with open("settings.yaml", "r", encoding="utf-8") as f:
    yaml_dict = yaml.load(f, yaml.CLoader)

class Window(tk.Tk):
    def __init__(self, row, h, w):
        super().__init__()
        self.title("Title")

        # 窗口配置
        self.window_width = h  # 默认600
        self.window_height = w  # 默认200
        screen_width = self.winfo_screenwidth()
        screen_height = self.winfo_screenheight()
        center_x = int(screen_width / 2 - self.window_width / 2)
        center_y = int(screen_height / 2 - self.window_height / 2)

        self.geometry(f'{self.window_width}x{self.window_height}+{center_x}+{center_y}')
        self.resizable(False, False)
        
        # 网格列配置
        self.columnconfigure(0, weight=1)
        self.columnconfigure(1, weight=2)
        self.columnconfigure(2, weight=2)
        self.columnconfigure(3, weight=2)
        self.columnconfigure(4, weight=1)

        # 修正行权重配置:遍历0到row-1的索引
        for i in range(row):
            self.rowconfigure(i, weight=1)
            
    def close(self):
        self.destroy()

def saveCfg(window, name_entry, password_entry):
    # 获取输入框的文本内容,而非控件对象
    yaml_dict['name'] = name_entry.get()
    yaml_dict['password'] = password_entry.get()
    # 写入YAML时指定编码,使用CDumper提高效率
    with open('settings.yaml', 'w', encoding="utf-8") as f:
        yaml.dump(yaml_dict, f, yaml.CDumper)
    window.close()

def userConfig():
    cfgWindow = Window(8, 300, 200)
    cfgWindow.title("Bot Configuration")
    
    nameLabel = ttk.Label(cfgWindow, text="Enter name below:", font='TkFixedFont')
    nameLabel.grid(column=2, row=1)
    name_entry = ttk.Entry(cfgWindow)
    name_entry.grid(column=2, row=2)
    
    passwordLabel = ttk.Label(cfgWindow, text="Enter password below:", font='TkFixedFont')
    passwordLabel.grid(column=2, row=3)
    password_entry = ttk.Entry(cfgWindow)
    password_entry.grid(column=2, row=4)
    
    # 调整参数名,更清晰区分控件和窗口
    confirmButton = ttk.Button(cfgWindow, text="Save Details", command=lambda: saveCfg(cfgWindow, name_entry, password_entry))
    confirmButton.grid(column=2, row=5)
    
    cfgWindow.mainloop()

userConfig()

原YAML文件(无需修改)

---
name: "name"
password: "password"

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 10:10:03