[英]Pickle module in Python and text files
我最近問了一個問題並收到了一個答案,我必須“腌制”我的代碼。 作為初學者,我不知道如何做到這一點。
因此,如果我通過查看您提出的與此相關的其他兩個問題( 1和2 )來正確理解,那么您的問題有兩個部分:
一個是生成一個包含用戶/密碼列表的文件,第二個是使用該文件來執行“登錄”系統。
寫入文件的問題在於您可以將文件視為文本...它並沒有真正保留Python list
的概念,因此您需要找到一種方法將您喜歡的users
列表列表轉換為文本和然后返回list
,以便您可以實際使用它。
有許多預制的序列化格式。 以下是一些: JSON 、 CSV 、 YAML ,或另一個用戶在另一個問題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__
的調用,並且文件將被關閉)
好的...所以我們在每一行都有一個username;password\\n
的文件。 讓我們使用它。
對於這一部分,您需要了解str
對象的split
(使用分號分隔用戶名和密碼)和rstrip
(刪除末尾的換行符\\n
)方法的作用。
我們需要從具有形狀username;password\\n
的一行文本“重建”兩個變量( username
和password
)。 然后查看是否在文件中找到了用戶名,如果是,提示用戶輸入密碼(並驗證它是否正確):
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 對象序列化為文件。 如果您想使用它,請按以下方式使用(至少是一種方式):
生成密碼文件:
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()
,您已經在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.