【发布时间】:2021-11-03 14:30:35
【问题描述】:
我做了一个简单的密码存储应用程序,但我只放了可能有问题的代码。当我从 python 运行这段代码时,它会按照我想要的方式运行,但是当我使用 pyinstaller 转换它时,它并不能按照我想要的方式运行。 每次我尝试注册并重新启动程序时,它都希望我一次又一次地注册。 当我在 storage.py 中登录信息并将注册变量设置为 True 然后将文件转换为 exe 时,它可以工作,但没有注册屏幕,只有登录屏幕。 此外,当我更改登录信息时,它不适用于新登录信息,我仍然必须使用旧登录信息。 我认为读取文件存在问题,因为写作效果很好。 我尝试了 --onedir 和 --onefile 模式,还使用 --add-data 添加文件,但仍然没有。
密码存储.py 文件:
from tkinter import *
from tkinter import messagebox
from resources.storage import *
root = Tk()
root.title('Password Storage')
root.iconbitmap('resources/password_storage.ico')
frame1 = LabelFrame(root, padx=10, pady=10)
frame1.grid(row=0, column=0, padx=5, pady=5)
def submit_register():
if username_register != '' and password_register != '':
registered = True
with open('resources/storage.py', 'w') as storage:
storage.write(f'\nregistered = {registered}\nstorage_username = \'{hashing(username_register.get())}'
f'\'\nstorage_password = \'{hashing(password_register.get())}\'')
storage.write('\n\nstorage = {\n')
for key, value in passwords.items():
storage.write(f'\t\'{key}\': {value},\n')
storage.write('}\n')
if messagebox.showinfo('Info', 'Successfully saved. Application needs to be restarted.') == 'ok':
root.quit()
else:
messagebox.showerror('Error', 'You didn\'t fill all input fields!')
def submit_login():
if username_login.get() == storage_username and password_login.get() == storage_password:
for widget in frame1.winfo_children():
widget.grid_forget()
else:
messagebox.showerror('Error', 'Wrong username or password!')
if not registered:
for widget in frame1.winfo_children():
widget.grid_forget()
Label(frame1, text='Register').grid(row=0, columnspan=2)
Label(frame1, text='New username: ').grid(row=1, column=0)
username_register = Entry(frame1, borderwidth=3)
username_register.grid(row=1, column=1)
Label(frame1, text='New password: ').grid(row=2, column=0)
password_register = Entry(frame1, borderwidth=3)
password_register.grid(row=2, column=1)
Button(frame1, text='Submit', command=submit_register).grid(row=3, columnspan=2)
elif registered:
for widget in frame1.winfo_children():
widget.grid_forget()
Label(frame1, text='Login').grid(row=0, columnspan=2)
Label(frame1, text='Username: ').grid(row=1, column=0)
username_login = Entry(frame1, borderwidth=3)
username_login.grid(row=1, column=1)
Label(frame1, text='Password: ').grid(row=2, column=0)
password_login = Entry(frame1, borderwidth=3)
password_login.grid(row=2, column=1)
Button(frame1, text='Submit', command=submit_login).grid(row=3, columnspan=2)
storage.py 文件:
registered = False
storage_username = ''
storage_password = ''
storage = {
}
【问题讨论】:
-
提供minimal reproducible example,导入时不要使用
* -
您的程序将密码作为 Python 源代码存储在
storage.py中。当您运行pyinstaller时,它会将源代码转换为字节码,而该字节码将被包装到.exe中。您的程序可能对storage.py的源代码进行的任何后续更改都不会影响.exe的行为方式:您的代码仍冻结在原始版本中。这就是它的工作原理。如果您想使用pyinstaller,那么将数据存储为 Python 源不是一个好的解决方案。看看pickle模块,它最像你正在做的,或者configparser。 -
谢谢,我会试试 BoarGules。顺便说一句,Matiiss,* 东西不起作用。
-
我可以用二进制模式写吗?
-
好吧,如果你愿意,你可以自己制作二进制文件布局,但是
pickle模块是一个很好的方法,它比你自己编写和调试的优势在于它是易于编写和调试的,并且将保存和加载任何 Python 数据结构,无论每行代码多么复杂。将其设置为方便的标准,并诚实地问自己是否认为自己也可以做到。如果你关心这些事情(虽然我无法想象为什么)pickle的默认协议是二进制。
标签: python tkinter pyinstaller