运行Tkinter Python程序时,我不断收到此错误:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python34\lib\tkinter\__init__.py", line 1533, in __call__
return self.func(*args)
File ".\tkintertesting2.py", line 18, in trylogin
if int(Password) == passcode:
ValueError: invalid literal for int() with base 10: ''
代码基本上从用户那里获取两个输入并比较它们以查看它们是否是有效凭据。目前,它打印出任何值都是错误的,并给出上面列出的错误:
import tkinter
def trylogin():
global wxy
global s
IDnumberz = s
Password = wxy
allowed_Usernames = [13702,1234,2]
allowed_PassCode = [8702,8535,1212]
for username in allowed_Usernames:
if int(IDnumberz) == username:
correct_username = 1
print ("good0")
break
else:
correct_username = 0
print (IDnumberz)
for passcode in allowed_PassCode:
if int(Password) == passcode:
correct_password = 1
print ("good1")
break
else:
correct_password = 0
print (Password)
if correct_password == 1 and correct_username == 1:
print ("Access granted. Welcome back!")
else:
print ("Uh oh! Something with your login was wrong!")
window = tkinter.Tk() #Create Window
window.title("AutoChange v1.3") #Rename window
window.geometry("600x600")
window.wm_iconbitmap('favicon.ico')
photo = tkinter.PhotoImage(file= "logo.gif")
photopacker = tkinter.Label(window, image=photo)
window.configure(background="#a1dbcd")
usernamelabel = tkinter.Label(window, text="Username", bg="#a1dbcd", )
usernamenter = tkinter.Entry(window,)
IDnumber = tkinter.IntVar()
s = IDnumber.get()
passwordlabel = tkinter.Label(window, text="Password", bg="#a1dbcd")
wxy = tkinter.IntVar()
passwordenter = tkinter.Entry(window, textvariable=wxy)
password = tkinter.StringVar()
wxy = password.get()
loginbutton = tkinter.Button(window, text="Login", bg="#a1dbcd",
command=trylogin)
#PACK
photopacker.pack()
usernamelabel.pack()
usernamenter.pack()
passwordlabel.pack()
passwordenter.pack()
loginbutton.pack()
window.mainloop() #Start Window
答案 0 :(得分:0)
这是一个基本的Python问题,与Tkinter部分无关。密码的值是“”; int(“”)将在Python中引发该错误。你不能取字符串的整数值;这些类型不起作用。您需要进行更正式的哈希/转换以与密码进行比较。
编辑回复Tmanzz122的评论:
这比我第一眼看到的要糟糕得多;你有几个错误堆叠在一起。
你有全局变量“password”和“wxy”,你还有一个名为“Password”的try_login本地变量,其值设置为wxy。 (我原来的答案是作为一个字符串值,而不是一个变量 - 我的错误,切换语言太频繁了。)那个局部变量是你实际上试图在你遇到崩溃时采取int()的变量。
当我去实际运行你的代码片段时,我添加了一个print语句,并注意到Password和wxy都有一个空白字符串作为它们的值。这是你问题的根源 - 你的价值没有传入。如果你看看你的崩溃痕迹,你也会看到它。
这是因为您无法通过简单的作业获得wxy
的值 - 您需要使用getter:
Password = wxy.get()
当我补充说,它仍然崩溃,这让我很困惑。崩溃是
AttributeError: 'str' object has no attribute 'get'
这意味着wxy不是你想要的StringVar,而是一个简单的字符串(这就是为什么当你使用它时它是一个空字符串)。罪魁祸首是你重新分配wxy的行是password.get()的结果后将它设置为你的textvariable。当我评论这条线路时,事情按预期工作 - 我没有登录,因为我把垃圾扔进了田地。
使用getter获取wxy的值,并且在使用它之前不要覆盖它,并且您将能够继续前进。祝你好运!
答案 1 :(得分:0)
您可以将您正在测试的密码转换为字符串,而不是将用户输入转换为int
:
if Password == str(passcode):
更好的解决方案是将字符串存储在密码列表中,这样就不需要进行转换,并且可以使用任何字符串(不仅仅是数字)。
您的算法的设计也有点怀疑,因为任何有效ID和密码的组合都将通过。通常,您希望将特定密码与特定ID相关联。
答案 2 :(得分:0)
我不同意其他回答者,他们说你的问题与tkinter
无关。确实如此。
核心问题是当您按下"登录"时,您不会从GUI读取用户ID和密码字段。按钮。相反,您正在访问s
和wxy
变量,这些变量包含的值一次可能属于这些字段,但在您按下该字段时可能不再存在按钮。
实际上s
会从全局变量IDnumber
(IntVar
)中读取初始值。虽然IDnumber
实际上并没有连接到任何东西,所以我怀疑它总是为零。 wxy
本身最初是IntVar
,并且挂钩在GUI中,但稍后会使用从password
变量(TextVar
)获取的值覆盖它。所以它可能总是一个空字符串。
要解决的首要问题是正确阅读Entry
字段中的值。
我建议如下,尽管可能有其他方法可以做更多或更少相同的事情(例如使用TextVar
,或者根本不使用变量包装器而只是在get
上调用Entry
{1}}自己,并自己进行整数转换):
usernamelabel = tkinter.Label(window, text="Username", bg="#a1dbcd", )
IDnumber = tkinter.IntVar()
usernamenter = tkinter.Entry(window, textvariable=IDnumber)
passwordlabel = tkinter.Label(window, text="Password", bg="#a1dbcd")
password = tkinter.IntVar()
passwordenter = tkinter.Entry(window, textvariable=password)
此时没有get
次来电!他们进入trylogin
函数:
def trylogin():
id_num = IDnumber.get()
password_num = password.get()
# ...
您不需要global
语句来访问全局变量(仅当您要为其分配新值时)。
这将起作用,假设您的用户在两个Entry
框中输入一个整数值。但是,如果他们不这样做(包括他们是否将一个或两个框留空),那么您将再次收到异常,因为IntVar.get
会对其int
调用值set
get
1}} to(在内部始终是一个字符串)。因此,您可能希望将try
个调用封装在except
/ def trylogin():
try:
id_num = IDnumber.get()
except ValueError:
print("invalid user ID") # replace this with some GUI error reporting?
return
try:
password_num = password.get()
except:
print("invalid password (must be an integer)")
return
# ...
块中,并在值不佳时执行某些操作。我不确定你的计划会有什么恰当的反应,所以我会把细节留给你。这是一般结构:
char inData[80];
byte index = 0;
void loop() {
while(Serial.available() > 0) {
char aChar = Serial.read();
if(aChar == '\n') {
// End of record detected. Parse this line
...
// When you're done parsing, clear the array and reset the index
inData[index] = NULL;
index = 0;
}
else {
inData[index] = aChar;
index++;
inData[index] = '\0'; // Keep the string NULL terminated
}
}
}
我怀疑代码中的逻辑存在其他问题,但我会停在此处,因为我认为这可以解决您当前代码中遇到的异常。
答案 3 :(得分:0)
有几件事情对你不利。有两个简单的修复:
您在创建窗口小部件后立即设置pasword
。在设置值之前,用户没有机会输入任何内容。相反,从trylogin
:
def trylogin()
password = passwordenter.get()
...
请注意,这不是解决方法。这是UI开发中非常非常常见的模式。
要注意的第二件事是,您不需要使用StringVar
或IntVar
。这些增加了开销,并没有为您提供任何好处(至少,不是您使用它们的方式)。您可以直接访问窗口小部件的内容,而无需窗口小部件的textvariable
属性。如果你愿意,你可以使用一个,但在这种情况下,它只是额外的开销。
您报告的错误消息是尝试将密码转换为整数,并且密码在转换时为空字符串。如果值具有除数字之外的任何值,则会出现类似错误(即:如果用户键入“5uper5ecretP @ ssw0rd!”)
最简单的解决方案是使用字符串作为允许的密码。如果这样做,检查密码就是一行代码:
allowed_PassCode = ['8702', '8535', '1212']
password = passwordenter.get()
# the one-line check:
if password in allowed_PassCode:
print ("good0")
如果您希望允许的密码实际上是整数,那很好。您只需将转换放在try / catch块中即可。这样,如果用户输入的内容不是数字,则密码将设置为None
,None
不在有效密码列表中,因此用户被锁定。
allowed_PassCode = [8702, 8535, 1212]
try:
password = int(passwordenter.get())
catch ValueError:
password = None
if password in allowd_PassCode:
...