I am creating a program with tkinter which comes with a default name and password stored in a text file. After login you need to open the Toplevel
window and type in the name and password you want to use in your subsequent logins. I have defined my variables but if I want to overwrite the text file I receive the below:
Error "NameError: name 'e1' is not defined"
Which I know I have defined.
import sys
from tkinter import messagebox
from tkinter import *
now = open("pass.txt","w+")
now.write("user\n")
now.write("python3")
now.close()
def login_in():
with open("pass.txt") as f:
new = f.readlines()
name = new[0].rstrip()
password = new[1].rstrip()
if entry1.get() == name and entry2.get() == password:
root.deiconify()
log.destroy()
else:
messagebox.showerror("error","login Failed")
def change_login():
ch = Toplevel(root)
ch.geometry('300x300')
e1 = Entry(ch, width=20).pack()
e2 = Entry(ch, width=20).pack()
sb = Button(ch, text="save", command=save_changes).pack()
def save_changes(): # function to change data in the txt file
data = e1.get() + "\n " + e2.get()
with open("pass.txt", "w") as f:
f.writelines(data)
root= Tk()
log = Toplevel()
root.geometry("350x350")
log.geometry("200x200")
entry1 = Entry(log)
entry2 = Entry(log)
button1 = Button(log, text="Login", command=login_in) #Login button
entry1.pack()
entry2.pack()
button1.pack()
label = Label(root, text="welcome").pack()
butt = Button(root, text="change data in file", command=change_login).pack()
root.withdraw()
root.mainloop()
So you have a few options here but in general you have 2 major issues.
The first issue is the use of
.pack()
after the creation of youre1
ande2
entry fields. This is a problem for theget()
method as the geometry manager will returnNone
if you pack this way. The correct method is to create the widget first withe1 = Entry(ch, width=20)
and then pack it on the next line withe1.pack()
this will allowget()
to work one1
.The second issue is the matter of local variables vs global variables. You have created
e1
ande2
inside of the functionchange_login()
and without telling python thate1
ande2
are global variables it will automatically assume you want them as local variables. This means the variables are only accessible from within the function they are created in.You have a few options and I will break them out for you.
1) The quick and dirty option is to assign
e1
ande2
as global variables. This can be done by usingglobal var_name, var2_name, and_so_on
so in this case add this line to the top of yourchange_login():
andsave_changes()
functions:This well tell python to add
e1
ande2
to the global name space and it will allowsave_changes()
to work with the variables in the global name space.2) Another method is to pass the 2 variables to
save_changes()
using the button command. We will need to uselambda
for this and we can accomplish this by adding:to the button created in
change_login()
and adding the 2 arguments tosave_changes()
like this:This will work just as well as the first option and it also avoids the use of global variables.
3) A third option is to create the entire program as a class and to use class attributes to allow the variables to work with all methods within the class.
Below is an example of your code using the 1st option:
Below is an example of your code using the 2nd option:
Below is an example of your code converted to a class and using class attributes to avoid the use of global variables.