Home > database >  Python can't find element that's there
Python can't find element that's there

Time:12-07

First and foremost, Python is not my first language, but a class I'm taking it is requiring it, so here I am... I'm using python with flask to make a website with a simple login/registration page. Making the pages is simple enough (I think?) however while setting the criteria for registration, the for loop I used to check if a user already exists worked at first, but with no changes to the code, it no longer does. I enter 'admin' as the username, but the loop can't find it despite existing in the txt file. Am I going insane or did I miss something?

def info():
    with open('passfile.txt', "r") as f:
        lines = f.readlines()
        for line in lines:
            text = line.split()
            username = text[0]
            print(text[0])
            password = text[1]

            yield username, password

def add_info(username, password):
    with open('passfile.txt', "a") as f:
        f.write(username   " "   password  "\n")


@week6.route("/registration", methods=["GET", "POST"])
def register():
    """
    function to register a new user
    """
    username, password = info()

    if request.method == "POST":
        un = request.form.get("username")
        pw = request.form.get("password")
        secure = sc.hash(str(pw))
        register.secure = secure
        print(un)
        if un in username:
            flash("That username is already taken")
            return render_template("registration.html")
        
        if pw_verify(pw) == True:
            add_info(un, secure)
            flash("Your officially registered!")
                
    return render_template("registration.html")

CodePudding user response:

Your problem is in how you're using your generator function:

def info():
    ...
    for line in lines:
        ...
        yield username, password

And then later:

username, password = info()

What the first function does (a generator function since it uses yield instead of return) is return an iterator that when you iterate over it gives you (username, password) tuples.

When you call it like username, password = info(), you're iterating it twice and assigning those tuples to username and password.

So, username might be ("user1", "secret_password") and password might be ("admin", "admin_password"), which clearly isn't what you intended.

It looks like what you wanted info to do, is return a list of usernames and a list of passwords. Changing it like this would work with your code:

def info():
    usernames = []
    passwords = []
    with open('passfile.txt', "r") as f:
        for line in f.readlines():
            username, password = line.split(maxsplit=1)

            usernames.append(username)
            passwords.append(password)

    return usernames, passwords

Although a quick fix, I would argue that that probably isn't the best way to solve this problem.

CodePudding user response:

Using yield turns a function into a generator. That means info actually returns an iterator. The first step is to change your info call to this:

users = info()

Iterators calculate their values on the fly, so the in operator won't work with them. You'll need to consume the iterator to see its contents. You can modify your if statement to use the any function and a comprehension.

if any(u[0] == un for u in users):

The comprehension yields a boolean based on the first element of the tuple yielded from info. The any function returns True if any element is true.

  • Related