簡體   English   中英

Python 和文本文件中的 Pickle 模塊

[英]Pickle module in Python and text files

我最近問了一個問題並收到了一個答案,我必須“腌制”我的代碼。 作為初學者,我不知道如何做到這一點。

因此,如果我通過查看您提出的與此相關的其他兩個問題( 12 )來正確理解,那么您的問題有兩個部分:

一個是生成一個包含用戶/密碼列表的文件,第二個是使用該文件來執行“登錄”系統。

寫入文件的問題在於您可以將文件視為文本...它並沒有真正保留Python list的概念,因此您需要找到一種方法將您喜歡的users列表列表轉換為文本和然后返回list ,以便您可以實際使用它。

有許多預制的序列化格式。 以下是一些: JSONCSVYAML ,或另一個用戶在另一個問題Pickle 中推薦的

由於在另一篇文章中您提到您將其用於學習目的,讓我們盡量保持簡單,好嗎?

讓我們將您的練習分成兩個 python 文件:一個只生成密碼文件,另一個嘗試讀取和驗證用戶輸入的用戶名/密碼。

腳本一:生成密碼文件。

所以...您有一個用戶名/密碼對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 的上下文管理器提供的“自動關閉”功能是一種更好的做法。 您可以將該腳本編寫為:

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塊的末尾時,將自動運行對 File 的特殊函數__exit__的調用,並且文件將被關閉)


腳本 2:使用密碼文件

好的...所以我們在每一行都有一個username;password\\n的文件。 讓我們使用它。

對於這一部分,您需要了解str對象的split (使用分號分隔用戶名和密碼)和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變量中獲得了 2 項 Python list 您無需從文本轉換為列表: unpickler器已經為您完成了。 這要歸功於picker.dump存儲到文件中的所有“額外”信息,這允許unpickler “知道”需要返回的對象是一個列表。

這是您使用pickle 創建登錄系統的方式,但是我不建議這樣做,因為存在很多安全問題。我更喜歡將python 連接到SQL 服務器並將密碼存儲在數據庫中。

import pickle

def register(username,password):
    user_details = dict()
    with open("users.txt",'rb') as f:
        user_details = pickle.load(f)
    if username in user_details:
        print "User already exsits"
    else:
        user_details[username] = password
        print "User added successfully"
    with open("users.txt",'wb+') as f:
        pickle.dump(user_details,f)

def login(username,password):
    user_details = dict()
    with open("users.txt",'rb') as f:
        user_details = pickle.load(f)
    if username in user_details:
        if user_details[username] == password:
            print "Correct Login successful"
        else:
            print "Incorrect Details"

def init():
    user_details = dict()
    with open("users.txt",'wb+') as f:
        pickle.dump(user_details,f)

init()
register("s","s")
login("s","s")

初始化調用 init() 函數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM