python - Python和文本文件中的Pickle模块

标签 python text-files pickle

我最近问了一个问题并收到了一个答案,我必须“修改”我的代码。作为一个初学者,我不知道该怎么做。

最佳答案

因此,如果我通过查看与此相关的另外两个问题(12)正确理解了您的问题,则分为两部分:

一种是生成包含用户/密码列表的文件,第二种是使用该文件来执行“登录”系统。

写入文件的问题是您可以将文件视为文本...它并没有真正保留Python list的概念,因此您需要找出一种方法将列表中的users列表转换为文本并然后返回列表的list,以便您可以实际使用它。

有许多预制的序列化格式。这里是一些:JSONCSVYAML,或另一个问题,Pickle中另一个用户推荐的

由于您在another post中提到您是出于学习目的而使用它,因此让我们尝试使其尽可能简单好吗?

让我们将练习分为两个python文件:一个仅生成密码文件,另一个尝试读取并验证用户输入的用户名/密码。

脚本1:生成密码文件。

所以...您有一个用户名/密码对的 list ,并且必须将其转换为文本,以便将其存储在文件中。让我们浏览列表中的每个条目并将其写入文件。如何利用Linux的一些启发并使用分号字符(;)在文件的每一行上标记用户名和密码之间的分隔?像这样:

sample_users = [
    ["user1", "password1"],
    ["user2", "password2"],
    ["user3", "password3"]
]
users_file = open("./users.txt", "w")
for sample_user in sample_users:
    username = sample_user[0]
    password = sample_user[1]
    users_file.write(username + ';' + password + '\n')
users_file.close()

将其放在.py文件中并运行它。它应该在脚本所在的同一目录上直接生成一个名为users.txt的文件。我建议您看一下该文件(任何文本编辑器都可以)。您会看到它看起来像这样:
user1;password1
user2;password2
user3;password3

顺便说一句,利用Python的context managers提供的“自动关闭”功能是更好的做法。您可以将该脚本编写为:
with open("./users.txt", "w") as users_file:
    for sample_user in sample_users:
        username = sample_user[0]
        password = sample_user[1]
        users_file.write(username + ';' + password + '\n')

看?无需调用.close()。如果在运行代码时发生了某些情况,将确保您离开with块后关闭文件(当解释器到达with块的末尾时,将自动运行对文件特殊功能 __exit__ 的调用,并且文件将被关闭)

脚本2:使用密码文件

好的...所以我们在每一行上都有一个username;password\n的文件。让我们使用它。

对于这一部分,您将需要了解split对象的 rstrip (使用分号分隔用户名和密码)和 \n (最后删除换行符str)的方法。

我们将需要从具有username形状的一行文本中“重建”两个变量(passwordusername;password\n)。然后查看是否在文件中找到了用户名,如果是,请提示用户输入密码(并确认密码正确):
def loginFunction():
    userEntry = ""
    foundName = False

    while userEntry == "":
        userEntry = raw_input("Enter your username: ")
        usersFile = open("users.txt", "r")
        for line in usersFile:
            print("This is the line I read:%s", line,)
            # Read line by line instead of loading the whole file into memory
            # In this case, it won't matter, but it's a good practice to avoid
            # running out of memory if you have reaaaally large files
            line_without_newline = line.rstrip('\n')       # Remove ending \n
            user_record = line_without_newline.split(';')  # Separate into username and password (make the line a list again)
            userName = user_record[0]
            password = user_record[1]
            # Might as well do userName, password = line_without_newline.split(';')
            if userName == userEntry:
                foundName = True
                print("User found. Verifying password.")
                passwordEntry = raw_input("Enter your password: ")
                if passwordEntry == password:
                    print "Username and passwords are correct"
                    break
                else:
                    print "incorrect"
                    userEntry = ""

        if not foundName:
            print("Username not recognised")
            userEntry = ""


if __name__ == "__main__":
    loginFunction()

我相信这应该做您想要的?如果您还有其他问题,请在答案中添加评论。

并祝您编码愉快!

PS:所以... pickle 怎么样?

Pickle是一个模块,可以“更安全”,更自动化地将Python对象序列化为文件。如果您想使用它,方法如下(至少是一种方法):
  • 生成密码文件:
    import pickle
    
    sample_users = [
        ["user1", "password1"],
        ["user2", "password2"],
        ["user3", "password3"]
     ]
    
     with open('./users.txt', 'w') as f:
         pickler = pickle.Pickler(f)
         for sample_user in sample_users:
            pickler.dump(sample_user)
    

    和以前一样,在这一点上,我建议您使用常规文本编辑器查看users.txt文件的外观。您会发现它与之前的文件完全不同(用户名和密码之间用半冒号分隔的文件)。就像这样:
        (lp0
        S'user1'
        p1
        aS'password1'
        p2
        a.(lp3
        S'user2'
        p4
        aS'password2'
        p5
        a.(lp6
        S'user3'
        p7
        aS'password3'
        p8
        a.%
    
  • 使用文件:
    import pickle
    
    def loginFunction():
        userEntry = ""
    
        while userEntry == "":
            userEntry = raw_input("Enter your username: ")
            usersFile = open("users.txt", "r")
            unpickler = pickle.Unpickler(usersFile)
            while True:
                try:
                    user_record = unpickler.load()
                    userName = user_record[0]
                    password = user_record[1]
                    if userName == userEntry:
                        print("User found. Verifying password.")
                        passwordEntry = raw_input("Enter your password: ")
                        if passwordEntry == password:
                            print "Username and passwords are correct"
                        else:
                            print "incorrect"
                            userEntry = ""
                        # Watch out for the indentation here!!
                        break  # Break anyway if the username has been found
    
    
                except EOFError:
                    # Oh oh... the call to `unpickler.load` broke 
                    # because we reached the end of the file and
                    # there's nothing else to load...
                    print("Username not recognised")
                    userEntry = ""
                    break
    
    
    if __name__ == "__main__":
        loginFunction()
    

  • 如果意识到,当您执行user_record = unpickler.load()时,您已经在list变量中获得了2个项目python user_record 。您无需从文本转换为列表:unpickler已经为您完成了此操作。这可以归功于picker.dump存储到文件中的所有“额外”信息,这使得unpickler“知道”需要返回的对象是一个列表。

    关于python - Python和文本文件中的Pickle模块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48013744/

    相关文章:

    python - 加载pickled数据时cPickle EOFError

    python - 如何在wx.Python中正确使用wx.CallLater

    c - 如何多次复制文件以在C中连续制作更大的文件

    javascript - 如何将文本文件中的数据读取到变量中,以便我可以根据值更改颜色?

    java - 读取txt文件并将所有内容显示为粗体

    python - python中基本类型的轻量级 pickle ?

    python - BeautifulSoup 对象不会 Pickle,导致解释器悄无声息地崩溃

    php - key 长度问题: AES encryption on phpseclib and decryption on PyCrypto

    python-3.x - 使用 plt.plot 与 plt.hist 的彩色图像直方图差异 [Python]

    python - 有没有办法在 python/opencv 中从单摄像头视频生成实时深度图?