4
\$\begingroup\$

I started Python 3 days ago. This user login code is the first project I completed, not following along with a tutorial. The idea is that you can create a user and login with it. I am wondering if there are ways to make this code much more efficient or shorter. If it needs anything, I'd love to learn new things.

def choices():
    print("Please choose what you would like to do.")
    choice = int(input("For Signing Up Type 1 and For Signing In Type 2: "))
    if choice == 1:
        print("Please Provide")
        username = str(input("Username: "))
        f = open("usernames.txt", 'r')
        info = f.read()
        if username in info:
            print("Username unavailable. Please Try Again.")
            return print(choices())
        f.close()
        password = str(input("Password: "))
        f = open("passwords.txt", 'r')
        info1 = f.read()
        f.close()
        f = open("usernames.txt", 'w')
        info = info + " " + username
        f.write(info)
        f.close()
        f = open("passwords.txt", 'w')
        info1 = info1 + " " + password
        f.write(info1)
        f.close()
        print("Congratulations! You have successfully created an account. You may now login in.")
        return print(choices())
    elif choice == 2:
        print("Please Provide")
        username = str(input("Username: "))
        f = open("usernames.txt", 'r')
        info = f.read()
        if username in info:
            password = str(input("Password: "))
            f = open("passwords.txt", 'r')
            info1 = f.read()
            if password in info1:
                print("Welcome Back " + username + "!")
            else:
                print("Your password is incorrect. Please try again.")
                return print(choices())
        else:
            print("Your username is either incorrect or nonexistent. You can either try again or create a new account.")
            return print(choices())
    else:
        raise TypeError


print(choices())
\$\endgroup\$

2 Answers 2

2
\$\begingroup\$

Use with to handle file operations

A common way to handle files is by creating a file instance with open statement and closing it when you are done with the handler, while this would work, it is prone to error. What if you forget to close the file? It leads to either the file not saving or the handler might be corrupted with garbage. with automatically closes the file once operations on it are done. A simple example is as follow

with open('usernames.txt', 'r') as f:
    f.read()

Recursion is expensive

Your choices function uses recursion which might become expensive. Recursion creates temporaries in the stack frame and as it recur more and more, your stack frame might eventually be filled, though it can be elegant to solve a problem with recursion, limit it usage. Any function that can be written recursively can also be written with an iterative approach. Iterative approach tends to be faster and does not create temporaries

Consider reducing the complexity of choices

Right now choice does way too much, signs up a user and also login a user. Your functions should do just one thing and do it very well. The name choices is very misleading, from the name, I would expect it to make a choice or rather I make a choice among a list of values, rather is suprisingly signs up and login a user. Avoid function side-effect. Function side-effect is when a function promises one thing and does another.

Use a dictionary pair

I really think a dictionary is needed in this scenario. Dictionaries as we all know are very fast. Storing a key-value pair of username and password makes the code clean and easy to reason about.

Detour

  1. You might want to use open('filename.txt', 'a') when you want to append to a file, using 'w' overwrites the content of the file and is similar to calling truncate on the file.

  2. When you want to recieve string input, no need for this statement str(input("Enter")), input automatically recieves strings.

  3. Avoid variable names suchh as f

This is an editted version of the code

def signup():
    with open("usernames.txt", 'r') as user:
        usernames = user.read().splitlines()
    with open("passwords.txt", 'r') as pwd:
        passwords = pwd.read().splitlines()
    
    info = dict(zip(usernames, passwords))

    print("Please Provide")
    username = input("Username: ")
    while username in info.keys():
        print("Username unavailable. Please Try Again.")
        username = input("Username: ")      
    password = input("Password: ")   
    
    with open("usernames.txt", 'a') as user:
        user.write(username + '\n')
    with open("passwords.txt", 'a') as pwd:
        pwd.write(password + '\n')
    
    print("Congratulations! You have successfully created an account. You may now login in.")

def login():
    with open("usernames.txt", 'r') as user:
        usernames = user.read().splitlines()
    with open("passwords.txt", 'r') as pwd:
        passwords = pwd.read().splitlines()
    
    info = dict(zip(usernames, passwords))
    username = input("Username: "))
    password = input("Password: "))

    if info.get(username, None) is None:
        print("Your username is either incorrect or nonexistent. You can either try again or create a new account.")
        signup()
        return

    if password != info[username]:
        print("Your password is incorrect. Please try again.")
        return

    print("Welcome Back " + username + "!")      

if __name__ == '__main__':
    print("Please choose what you would like to do.")
    choice = int(input("For Signing Up Type 1 and For Signing In Type 2: "))
    if choice == 1:
        signup()
    elif choice == 2:
        login()

\$\endgroup\$
0
\$\begingroup\$

ere are the points in your code that needs to be fixed:

  1. Calling a function inside that function would sooner or later result in a RecursionError error. instead, use while loop, and a break statement for when a user successfully logs in. Whenever invalid information is given, the continue statement will make the program jump to the top of the while loop again.

  2. Always use a with statement over simply assigning an open function to a variable.

  3. It is unnecessary to convert the user's input to an integer, especially when it is prone to cause aValueError when the user inputs any characters tat aren't digits.

  4. There is no need to convert the user's input into a string, as the input will be of string type by default. Doing so only wastes efficiency.

  5. Checking if a string is in a file in its single-string form will cause bugs. For example, if your file is currently:

Sally Bobby Timmy Bobble Deusovi Bubbler Ention

and the user inputs "Bob", the program will assume that "Bob" is among the usernames. Instead of spaces as the delimiter, which can cause confusion when a user inputs their last name, use line breaks \n, and convert the file's content into a list of names before checking if the user's input is valid.

Here is the full implementation:

def choices():
    while True:
        print("Please choose what you would like to do.")
        choice = input("For Signing Up Type 1 and For Signing In Type 2: ")
        if choice == '1':
            print("Please Provide")
            username = input("Username: ")
            with open("usernames.txt", 'r') as f:
                info = f.read()
                if username in info:
                    print("Username unavailable. Please Try Again.")
                    continue
            password = input("Password: ")
            with open("passwords.txt", 'r') as f:
                info1 = f.read()
            with open("usernames.txt", 'w') as f:
                info = f'{info}\n{username}'
                f.write(info)
            with open("passwords.txt", 'w') as f:
                info1 = f"{info1}\n{password}"
                f.write(info1)
            print("Congratulations! You have successfully created an account. You may now login in.")
        elif choice == '2':
            print("Please Provide")
            username = input("Username: ")
            with open("usernames.txt", 'r') as f:
                info = f.read().splitlines()
                if username in info:
                    password = input("Password: ")
                    with open("passwords.txt", 'r') as f:
                        info1 = f.read().splitlines()
                        if password in info1:
                            print(f"Welcome Back {username}!")
                            break
                        print("Your password is incorrect. Please try again.")
                else:
                    print("Your username is either incorrect or nonexistent. You can either try again or create a new account.")
        else:
            print("Invalid option.")
choices()
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.