Python密码管理器报decrypted变量未定义错误修复
问题原因
报错核心是两个层面的问题:
- 变量作用域错误:
decrypted是你写在add()函数嵌套的logic()函数里的局部变量,和saved()函数不在同一个作用域,saved()根本访问不到这个变量。而且就算你加了全局声明,只要用户没点过保存按钮触发logic()执行,decrypted就从来没被赋值过,点查看密码的时候必然报未定义错误。 - 加密逻辑本身有严重bug:每次保存密码都会重新生成新的加密密钥,之前存的所有密码会永久无法解密;解密完成后你反而把加密后的乱码写回了明文密码文件,后续读写全是错的。
修复方案
- 调整密钥初始化逻辑,密钥只在第一次运行程序时生成,不要每次存密码都替换密钥,把这段代码放到全局初始化位置(也就是
window=customtkinter.CTk()这行下面):KEY_PATH = "MyKey.key" ENC_FILE_PATH = "enc_passwords.txt" # 密钥不存在才生成 if not os.path.exists(KEY_PATH): init_key = Fernet.generate_key() with open(KEY_PATH, "wb") as key_file: key_file.write(init_key) # 全局加载加密器 with open(KEY_PATH, "rb") as key_file: crypto_key = key_file.read() fernet = Fernet(crypto_key) - 重写
logic()里的加密存储逻辑,删掉错误的明文写入、重复生成密钥的代码,改成追加新条目后统一加密存储:def logic(): # 非空校验 if platform_.get() == "" or user.get() == "" or password.get() == "": mb.showerror("WRONG INPUT","Please Make sure to enter all the fields \nIf you don't have a username/password Enter 'None'") return # 拼接新的密码条目 new_entry = f"Platform: {platform_.get()} | Username/Email: {user.get()} | Password: {password.get()}\n" # 读取已有加密内容,解密后追加新条目 exist_content = b"" if os.path.exists(ENC_FILE_PATH): with open(ENC_FILE_PATH, "rb") as enc_file: exist_content = fernet.decrypt(enc_file.read()) exist_content += new_entry.encode("utf-8") # 重新加密写回文件 encrypted = fernet.encrypt(exist_content) with open(ENC_FILE_PATH, "wb") as enc_file: enc_file.write(encrypted) # 清空输入框 platform_.delete(0, END) user.delete(0, END) password.delete(0, END) mb.showinfo("Success", "Password saved") - 重写
saved()函数,不要访问不存在的局部变量,直接读取加密文件现场解密,同时修正多窗口的写法:def saved(): if not os.path.exists(ENC_FILE_PATH): mb.showinfo("Tip", "No saved passwords yet") return # 读文件解密 with open(ENC_FILE_PATH, "rb") as enc_file: decrypted_content = fernet.decrypt(enc_file.read()).decode("utf-8") # 子窗口用Toplevel不要新建CTk主窗口,避免事件循环冲突 new_window = customtkinter.CTkToplevel(window) new_window.title("Saved Passwords") new_window.geometry("650x400") saved_passwords = customtkinter.CTkLabel(new_window, text=decrypted_content, justify="left") saved_passwords.pack(padx=20, pady=20, fill="both", expand=True) - 删掉原代码里把加密内容写回
pass.txt的错误代码,不要留存明文密码文件,所有密码统一存在加密后的enc_passwords.txt里,避免明文泄露。
额外优化提示
- 你在各个嵌套函数里反复调用
main_func()会重复生成侧边按钮组件,造成内存泄漏,只需要在页面切换时保留侧边按钮就可以,不需要每次重绘。 - 原代码里写的
global encrypted没有实际作用,Python中函数内给变量赋值时,需要在函数内部声明global才会关联全局变量,修复后不需要全局变量存储加解密内容,随用随读文件更安全。
内容的提问来源于stack exchange,提问作者user19164169
相关产品推荐
相关产品推荐

