【问题标题】:Verifying Username and Password in a Text File in Python在 Python 中验证文本文件中的用户名和密码
【发布时间】:2023-04-11 06:41:01
【问题描述】:

第一次在这里发帖,虽然我已经潜伏多年了

我目前正在从事一个编程项目并且被卡住了。该项目的目标是获取用户的输入、用户名和密码,并通过文本文件验证是否正确。如果正确,它将打印“欢迎!”最后,如果没有,它会询问用户名和密码并循环,直到输入正确的组合。

文本文件格式如下:

达斯:维达

波巴:费特

R2:D2

欧比旺:克诺比

卢克:天行者

这是我的代码:

# Lets user know what this program will do
print("Please login");

# Opens accounts txt file
accounts_file = open("accounts.txt", "r")

# Flag to terminate while loop
complete = False
# Runs loop until username and password are correct
while complete == False:
    # Asks user for username and stores as variable
    usernameInput = input("Username:");
    # Asks user for password and stores as variable
    passwordInput = input("Password:");
    # Reads each line of the text file line by line
    # Darth:Vader
    # Luke:Skywalker
    # R2:D2
    # ObiWan:Kenobi
    # Boba:Fett
    for line in accounts_file:
        # Stores each line in file as a username/password combo
        username, password = line.replace("\n","").split(":")
        # If username and password match, breaks out of the loop and sets complete to  True
        if usernameInput == username and passwordInput == password:
            complete = True
            break
        # Sets complete to False and loops back    
        else:
            complete = False
            continue
if complete == True:
    print("Welcome!");

如果第一次输入正确的名称,我可以让它正确运行: 例如:

请登录:

用户名:达斯

密码:维达

欢迎!

  • 结束程序

如果我输入了错误的名字,它会像这样循环回来:

请登录:

用户名:达斯

密码:费特

用户名:.....

但是,如果我输入了错误的用户名,然后又输入了正确的用户名,它不会像我想要的那样结束程序,并继续循环:示例:

请登录:

用户名:Luke 密码:Vader

用户名:Darth 密码:Vader

用户名:R2 密码:D2

知道是什么导致它不接受用户的下一个输入并完成循环吗?

感谢您的帮助!

【问题讨论】:

  • 我不确定,但可能文件迭代器在第一次迭代中已经用尽,所以当你进入第二次尝试时,没有更多的行了。也许尝试而不是使用文件处理程序将所有行存储在带有.readlines() 的列表中。
  • 顺便说一下,Sets complete to False and loops back 部分是不必要的。您不需要将complete 设置为False,因为它已经是False。如果它是 True 你已经结束了 for 循环和 while 循环。而且您不需要continue,因为您将在到达 for 循环末尾后自动继续。

标签: python


【解决方案1】:

这样做是因为您的文件在您第二次尝试读取时为空。

第一次在这里运行整个文件后:

for line in accounts_file:
        # Stores each line in file as a username/password combo
        username, password = line.replace("\n","").split(":")
        # If username and password match, breaks out of the loop and sets complete to  True
        if usernameInput == username and passwordInput == password:
            complete = True
            break
        # Sets complete to False and loops back    
        else:
            complete = False
            continue

该文件是空的,因此称为“已耗尽”。 如果用户错了,您每次都需要重新创建一个新的文件对象。就这样做吧:

accounts_file = open("accounts.txt", "r")
for line in accounts_file:
        # Stores each line in file as a username/password combo
        username, password = line.replace("\n","").split(":")
        # If username and password match, breaks out of the loop and sets complete to  True
        if usernameInput == username and passwordInput == password:
            complete = True
            break
        # Sets complete to False and loops back    
        else:
            complete = False
            continue
account_file.close() # Very important to close the file for next time!

或者你可以像这样使用with ... as ...

with open("accounts.txt", "r") as accounts_file:
    for line in accounts_file:
        # Stores each line in file as a username/password combo
        username, password = line.replace("\n","").split(":")
        # If username and password match, breaks out of the loop and sets complete to  True
        if usernameInput == username and passwordInput == password:
            complete = True
            break
        # Sets complete to False and loops back    
        else:
            complete = False
            continue

【讨论】:

  • 你说得对,这也是一种方式,更好的方式,我加了,谢谢
  • @Eladtopaz 这很完美!我有一种感觉,要么第二次不存储用户的输入,要么存储它,但没有将它与任何东西进行比较。感谢您的帮助和出色的回答!
【解决方案2】:

一旦你打开一个文件并遍历它,迭代器就会耗尽。仅仅因为您的外部循环进入另一个迭代不会重新启动文件迭代。

当您执行for x in [1, 2, 3]: 时,python 会在后台调用iter([1, 2, 3]。对于列表,这每次都会返回一个新的迭代器对象。当类似的循环调用iter(accounts_file) 时,返回一个新的迭代器:文件对象迭代器。

您有两个基本选项来重新开始迭代:

  1. 每次都重新打开文件。通常,惯用的方法是使用 with 块,因为这样也会在出现错误时自动关闭文件:

    while not complete:
        usernameInput = input("Username:")
        passwordInput = input("Password:")
        with open("accounts.txt", "r") as accounts_file:
            for line in accounts_file:
                username, password = line.replace("\n","").split(":")
                if usernameInput == username and passwordInput == password:
                    complete = True
                    break
    

    此选项不太理想,因为每次用户输入错误选项时它都会执行大量磁盘 I/O。

  2. 将整个文件加载到列表中。这使您可以一遍又一遍地迭代而无需多次访问磁盘。您可以在循环之前预加载,或者在第一次输入之后懒惰地执行。第一个选项显示在这里:

    with open("accounts.txt", "r") as accounts_file:
        lines = accounts_file.readlines()
    while not complete:
        usernameInput = input("Username:")
        passwordInput = input("Password:")
         for line in lines:
             username, password = line.replace("\n","").split(":")
             if usernameInput == username and passwordInput == password:
                 complete = True
                 break
    

第三种选择是这两者的混合,这可能适用于大文件。您可以将索引预加载到文件中,然后根据用户输入查找小型 sn-ps。

请注意,else 子句不是必需的。 completeFalse,只有在你想跳出循环时才会改变。

while not complete: 更习惯。 while 循环条件中的表达式始终被解释为布尔值:无需明确比较。即便如此,bool 的值 TrueFalse 都是单例。在需要显式比较它们的相对罕见的情况下,使用身份运算符is 而不是==。即,complete is Falsecomplete == False 更 Pythonic。

您实际上可以通过使用for 循环的神秘功能完全摆脱complete 变量:else 子句。每当循环完成而不中断时,都会触发此子句:

while True:
    usernameInput = input("Username:")
    passwordInput = input("Password:")
    with open("accounts.txt", "r") as accounts_file:
        for line in accounts_file:
            username, password = line.replace("\n","").split(":")
            if usernameInput == username and passwordInput == password:
                   break
        else:
            continue
        break

另外,不要在 python 中正常使用分号。它们不是无效的,但它们不是常规的,除非在命令行交互等极少数情况下。

【讨论】:

  • complete 变量是必需的。在您的代码示例中,当您想同时跳出 for 循环和 while 循环时,您才跳出 for 循环。
  • @hostingutilities.com。谢谢你的收获。我已经更新了。有一种方法可以在没有 completed 的情况下制定这一点,但它不是主要答案的一部分。
  • 感谢您的解释,这让我们更清楚地了解了为什么它不起作用。我很欣赏这种洞察力。
  • 作为 for-else 的替代方案,我更喜欢将 while 循环放在它自己的函数中,当我想结束两个循环时可以退出。
【解决方案3】:

这个怎么样:-

ACCOUNTS = {}
with open('accounts.txt') as afile:
    for line in afile.readlines():
        tokens = line.split(':')
        ACCOUNTS[tokens[0]] = tokens[1].strip()
print('Please log in')
while True:
    n = input('Please enter your name: ')
    p = input('Please enter your password: ')
    if (password := ACCOUNTS.get(n)) and password == p:
        break
    print('Incorrect username or password')
print('Welcome')

【讨论】:

    【解决方案4】:
    print("Please Login !")
    accounts_file = open("accounts.txt", "r")
    USERS = []
    for line in accounts_file:
        if line.replace("\n","").split(":") != [""]:
            accounts.append(line.replace("\n","").split(":"))
    accounts_file.close()
    
    
    def passCheck(username , password):
        if [username,password] in USERS:
            return   
        else:
            return passCheck(input("Enter your username : ") , input("Enter your password"))
    passCheck(input("Enter your username : ") , input("Enter your password"))
    print("Welcome!")
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多