Python和文本文件中的Pickle模块 [英] Pickle module in Python and text files

查看:116
本文介绍了Python和文本文件中的Pickle模块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

解决方案

因此,如果我通过查看其他两个问题来正确理解( 1 2 )与此相关的问题,您的问题分为两个部分:

一个正在生成一个包含用户/密码列表的文件,第二个正在使用该文件进行登录"系统.

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

有许多预制的序列化格式.以下是一些示例: JSON YAML ,或另一个用户在另一个问题中推荐的 Pickle

另一个帖子,您提到您是出于学习目的而使用它,让我们尝试使其尽可能简单好吗?

让我们将练习分为两个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的

看到了吗?无需调用.close().如果在运行代码时发生了某些情况,将确保您在离开with块之后关闭文件(当解释器到达with块的末尾时,将调用文件的特殊功能 split (使用分号分隔用户名和密码)和 rstrip rstrip 方法(最后删除换行符号\n).

我们将需要从形状为username;password\n的一行文本中重建"两个变量(usernamepassword).然后查看是否在文件中找到了用户名,如果是,请提示用户输入密码(并确认密码正确):

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是一个模块,可以更安全",更自动化地将Python对象序列化为文件.如果您想使用它,方法如下(至少是一种方法):

  1. 生成密码文件:

    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.%
    

  2. 使用文件:

    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()时,您已经在user_record变量中获得了两个项目Python list .您无需从文本转换为列表:unpickler已经为您完成了此操作. picker.dump将所有额外"信息存储到文件中,使得unpickler知道"需要返回的对象是一个列表,这是有可能的.

I have recently asked a question and received an answer that I must 'pickle' my code. As a beginner, I have no idea how to do that.

解决方案

So, if I understood correctly by looking at the other two questions (1 and 2) you made related to this, your problem has two parts:

One is generating a file with a list of user/passwords and the second is using that file to do a "login" system.

The problem with writing to files is that you can regard a file as just text... It doesn't really retain the concept of a Python list so you need to figure out a way to convert your fancy users list of lists to text and then back to a list of lists so you can actually use it.

There are many pre-made serializing formats. Here are a few: JSON, CSV, YAML, or the one another user recommended in another question, Pickle

Since in another post you mentioned that you're using this for learning purposes, let's try to keep it as simple as possible ok?

Let's split your exercise in two python files: One to just generate the passwords file and the other that tries to read and verify the username/password that the user entered.

Script 1: Generate the password file.

So... You have a list of username/password pairs, and you have to transform that to text so you can store it in a file. Let's just go through each entry in the list and write it to a file. How about using a bit of inspiration from Linux and use the semicolon character (;) to mark the separation between username and password on each line of the file? Like this:

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()

Put that in a .py file and run it. It should generate a file called users.txt right on the same directory where the script is located. I suggest you take a look to the file (any text editor will do). You'll see it looks like this:

user1;password1
user2;password2
user3;password3

By the way, it's a much better practice taking advantage of the "autoclosing" features provided by Python's context managers. You could write that script as:

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')

See? No call to .close() needed. If something happens while running the code, you will be assured that your file is closed after leaving the with block (when the interpreter reaches the end of the with block, a call to the File's special function __exit__ will be automatically run, and the file will be closed)


Script 2: Use the passwords file

Ok... So we have a file with username;password\n on each line. Let's use it.

For this part, you're gonna need to understand what the split (to separate username and password using the semicolon) and rstrip (to remove the newline symbol \n at the end) methods of the str objects do.

We're gonna need to "rebuild" two variables (username and password) from a line of text that has the shape username;password\n. Then see if the username is found in the file, and if so, prompt the user for the password (and verify it's correct):

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()

I believe this should do what you want? Put a comment in the answer if you have other questions.

And have fun coding!


PS: So... How about pickle?

Pickle is a module that serializes Python objects into files in a "safer" and more automated way. If you wanted to use it, here's how (one way, at least):

  1. Generating the passwords file:

    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)
    

    As before, at this point I would recommend you take a look to how the file users.txt looks like with a regular text editor. You'll see it's pretty different to the file before (the one with the username and password separated by semi colons). It's something like this:

        (lp0
        S'user1'
        p1
        aS'password1'
        p2
        a.(lp3
        S'user2'
        p4
        aS'password2'
        p5
        a.(lp6
        S'user3'
        p7
        aS'password3'
        p8
        a.%
    

  2. Use the file:

    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()
    

If you realize, when you do user_record = unpickler.load(), you already get a 2 items Python list in the user_record variable. There's no need for you to transform from text onto list: the unpickler has already done that for you. This is possible thanks to of all that "extra" information that was stored by picker.dump into the file, which allows the unpickler to "know" that the object that needs to be returned is a list.

这篇关于Python和文本文件中的Pickle模块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆