User login read from file failing compared to user input

时间:2016-08-31 18:03:52

标签: python python-2.7 file user-input

I'm writing a program that will verify a username:

def user_login():
    """ Login and create a username, maybe """
    with open('username.txt', 'r') as f:
        if f.readline() is "":
            username = raw_input("First login, enter a username to use: ")
            with open('username.txt', 'a+') as user:
                user.write(username)
        else:
            login_id = raw_input("Enter username: ")
            if login_id == str(f.readline()):
                return True
            else:
                print "Invalid username."
                return False


if __name__ == '__main__':
    if user_login() is not True:
        print "Failed to verify"

Everytime I run this it outputs the following:

Enter username: tperkins91
Invalid username.
Failed to verify

How do I compare user input to reading from a file?

2 个答案:

答案 0 :(得分:1)

Opening the same file again in another nested context is not a good idea. Instead, open the file once in append mode, and use f.seek(0) to return to the start whenever you need to:

def user_login():
    """ Login and create a username, maybe """
    with open('username.txt', 'a+') as f:
        if f.readline() is "":
            username = raw_input("First login, enter a username to use: ")
            f.seek(0)
            f.write(username)
            # return True/False --> make the function return a bool in this branch
        else:
            login_id = raw_input("Enter username: ")
            f.seek(0)
            if login_id == f.readline():
                return True
            else:
                print "Invalid username."
                return False


if __name__ == '__main__':
    if user_login() is not True:
        print "Failed to verify" 

Returning a bool value in the if branch is something you may want to consider so the return type of your function is consistent as bool, and not None as in the current case.

答案 1 :(得分:1)

When you use readline() the first time the current file position is moved past the first record. A better way to find if the file is empty is to test it's size:

import os.path
import sys

def user_login():
    fname = 'username.txt'

    """ Login and create a username, maybe """
    if os.path.getsize(fname) == 0:

        with open(fname, 'w') as f:
            username = raw_input("First login, enter a username to use: ")
            f.write(username)
            return True    #/False --> make the function return a bool in this branch
    else:
        with open(fname, 'r') as f:
            login_id = raw_input("Enter username: ")
            if login_id == f.readline().rstrip():
                return True
            else:
                print >>sys.stderr, "Invalid username."
                return False


if __name__ == '__main__':
    if user_login() is not True:
        print "Failed to verify"

f.readline() will include a trailing newline, if there is one in the file, whereas raw_input() will not. While we don't explicitly write one, someone might edit the file and add a newline unintentionally, hence the addition of the rstrip() as a defensive precaution.