Python 和文本文件中的 Pickle 模块
Pickle module in Python and text files
我最近提出了一个问题并得到了一个答案,我必须 'pickle' 我的代码。作为初学者,我不知道该怎么做。
这是您使用 pickle 创建登录系统的方式,但是我不推荐这种方式,因为它有很多安全性 issue.I 更愿意将 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() 函数。
所以,如果我通过查看你提出的与此相关的其他两个问题 (1 and 2) 理解正确,那么你的问题有两个部分:
一个正在生成一个包含 user/passwords 列表的文件,第二个正在使用该文件做一个 "login" 系统。
写入文件的问题在于,您可以将文件视为文本...它并没有真正保留 Python list
所以你需要找到一种方法将你喜欢的 users
列表转换为文本,然后再转换回 list
列表,这样你就可以实际使用它了。
有许多预制的序列化格式。这里有一些:JSON, CSV, YAML, or the one another user recommended in another question, Pickle
既然您在 another post 中提到您将其用于学习目的,那么让我们尽量保持简单,好吗?
让我们将练习分成两个 python 文件:一个只生成密码文件,另一个尝试读取和验证用户输入的 username/password。
脚本 1:生成密码文件。
所以...您有 list
对 username/password,您必须将其转换为文本,以便将其存储在文件。让我们浏览列表中的每个条目并将其写入文件。借鉴一下 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 提供的 "autoclosing" 功能是一个更好的练习。您可以将该脚本编写为:
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
。让我们使用它。
对于这一部分,您需要了解 str
对象的 split
(to separate username and password using the semicolon) and rstrip
(删除末尾的换行符 \n
)方法的作用。
我们需要 "rebuild" 两个变量(username
和 password
)来自形状为 username;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 是一个以 "safer" 和更自动化的方式将 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
存储到文件中的所有 "extra" 信息,它允许 unpickler
到 "know" 需要返回的对象是一个列表。
我最近提出了一个问题并得到了一个答案,我必须 'pickle' 我的代码。作为初学者,我不知道该怎么做。
这是您使用 pickle 创建登录系统的方式,但是我不推荐这种方式,因为它有很多安全性 issue.I 更愿意将 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() 函数。
所以,如果我通过查看你提出的与此相关的其他两个问题 (1 and 2) 理解正确,那么你的问题有两个部分:
一个正在生成一个包含 user/passwords 列表的文件,第二个正在使用该文件做一个 "login" 系统。
写入文件的问题在于,您可以将文件视为文本...它并没有真正保留 Python list
所以你需要找到一种方法将你喜欢的 users
列表转换为文本,然后再转换回 list
列表,这样你就可以实际使用它了。
有许多预制的序列化格式。这里有一些:JSON, CSV, YAML, or the one another user recommended in another question, Pickle
既然您在 another post 中提到您将其用于学习目的,那么让我们尽量保持简单,好吗?
让我们将练习分成两个 python 文件:一个只生成密码文件,另一个尝试读取和验证用户输入的 username/password。
脚本 1:生成密码文件。
所以...您有 list
对 username/password,您必须将其转换为文本,以便将其存储在文件。让我们浏览列表中的每个条目并将其写入文件。借鉴一下 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 提供的 "autoclosing" 功能是一个更好的练习。您可以将该脚本编写为:
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
。让我们使用它。
对于这一部分,您需要了解 str
对象的 split
(to separate username and password using the semicolon) and rstrip
(删除末尾的换行符 \n
)方法的作用。
我们需要 "rebuild" 两个变量(username
和 password
)来自形状为 username;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 是一个以 "safer" 和更自动化的方式将 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
存储到文件中的所有 "extra" 信息,它允许 unpickler
到 "know" 需要返回的对象是一个列表。