0

I'm very very new to Python so no doubt there are several very basic mistakes, although I have looked through several Python tutorials and everything seems ok.

I'm trying to import two text files in to my list.

The username.txt looks like this

user1
user2
user3

and the password.txt looks like this

pass1
pass2
pass3

when I run everything the debugger doesn't give me any errors but when I try a user/password combination it says that it isn't correct.

Can you see anything wrong, or know anything that might help?

This is what I am running:

from Tkinter import *

username = ["nathan"]
password = ["1"]

def login():
        index = 0
        usrnm = usernameEntry.get()
        while index < len(username):
                if username[index] == usrnm:
                        psswrd = passwordEntry.get()
                        if password[index] == psswrd:
                                print("Success")
                                break
                        else:
                                print("Password doesn't exist!")
                                break
                else:
                        index = index + 1
        else:
                print("Username doesn't exist!")

def save():
        fWUsername = open("username.txt", "w")
        fWUsername.write("\n".join(str(x) for x in username))
        fWUsername.close

        fWPassword = open("password.txt", "w")
        fWPassword.write("\n".join(str(x) for x in password))
        fWPassword.close

def load():
        fRUsername = open("username.txt", "r")
        username = fRUsername.readlines()
        fRUsername.close()

        fRPassword = open("password.txt", "r")
        password = fRPassword.readlines()
        fRPassword.close()

loginForm = Tk()

usernameLabel = Label(loginForm, text = "username:")
usernameLabel.pack()

usernameEntry = Entry(loginForm)
usernameEntry.pack()

passwordLabel = Label(loginForm, text = "password:")
passwordLabel.pack()

passwordEntry = Entry(loginForm, show = "*")
passwordEntry.pack()

submitButton = Button(loginForm, text = "submit", command = login)
submitButton.pack()

loadButton = Button(loginForm, text = "load data lists", command = load)
loadButton.pack()

saveButton = Button(loginForm, text = "save data lists", command = save)
saveButton.pack()

mainloop()
5
  • What error message do you get? That code shouldn't do much as the login, save and load methods are never called. Commented Sep 2, 2013 at 12:52
  • do a print username after username = fRUsername.readlines() and see if the format is as you expect. Commented Sep 2, 2013 at 12:55
  • 1
    Mike Vella, when I click the 'loadButton' it calls the load method, but I don't get an error message. What I want to happen is the contents of the user and password txts replace the contents of the current lists so when I enter them in to the entry box it prints success Commented Sep 2, 2013 at 13:00
  • Fredrik, they aren't; they have "/n" on the end of each, is there a way to get rid of this? Commented Sep 2, 2013 at 13:02
  • to get rid of the trailing newline characters use strip() Commented Sep 2, 2013 at 13:39

2 Answers 2

1

That’s actually a mean issue you have here, because it’s not really obvious at all. As a tip, you can easily print some additional information throughout your code to give you an idea of what’s going wrong.

In this case, I put a print(username) at the beginning of the login function and saw that only nathan is a valid user, although I clicked the load button before.

So what’s happening?

The variables username and password are both defined at the root of the module (the script); this makes them global variables. Global variables can be accessed from anywhere within the module—unless they are hidden by local variables of the same name. Now, while they can be accessed from anywhere, changing them is not possible by default.

So within your load function, you have this:

username = fRUsername.readlines()

This will declare a local variable within your function, hiding the global variable. When the function ends, that local variable is thrown away; but your global variable is unchanged.

To change this behaviour, you can define that you want to use the global variables username and password. To do that, add a global statement for them at the beginning of the function:

def load():
    global username, password
    username = ... # this now changes the _global_ variable

If you do that, the global variables are correctly changed and all usernames are available from the login function.

However, readlines will include line breaks after each line. So the usernames will actually be user1\n, user2\n and user3 (same with the passwords). To fix that, you might want to strip() those values before comparing them (removing all leading and trailing whitespace).

Finally, it is generally recommmended to use the with statement when opening files. This will make sure that the handles are correctly closed (you don’t need to call close() explicitely—which you aren’t doing in the save method btw!):

with open('username.txt', 'r') as fRUsername:
    username = fRUsername.readlines()
Sign up to request clarification or add additional context in comments.

4 Comments

global is a horrid statement to suggest to a beginner since there is almost never a reason to use them in Python.
@msw You are more than welcome to write an extensive answer yourself and explain how to structure the whole application in a better way to avoid having to use global. In this case, it’s still the simplest solution to fix this issue, and I think it helps beginners more to fix their solution than to propose a complete rewrite into something that they didn’t come up with themselves.
I read somewhere that on non-Unix systems the symbol for line breaks is different, so the strip may not work the same? Is this true, and, if so, is there a way to remove it for both Unix and non-Unix systems?
No, str.strip will by default remove any whitespace, including unix line breaks \n and Windows’ combined \r\n, but also including spaces which you might want to get rid of for logins anyway.
0

At first glance, the code looks correct. A good way to solve problems like this is adding logging to make sure the code does what you expect when you run it. Think of logging as a protocol that allows you to debug a problem afterwards. It's a very useful skill to have.

In your case, you should add logging after loading user names and passwords (print how many you loaded). If the two numbers disagree or both are 1, you already know that something is wrong.

Later, when searching users and passwords, print the index and the expected password.

Note: For security reasons, you shouldn't print passwords during logging. Log files are often only weakly protected.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.