我最近问了一个问题并收到了一个答案,我必须“修改”我的代码。作为一个初学者,我不知道该怎么做。
最佳答案
因此,如果我通过查看与此相关的另外两个问题(1和2)正确理解了您的问题,则分为两部分:
一种是生成包含用户/密码列表的文件,第二种是使用该文件来执行“登录”系统。
写入文件的问题是您可以将文件视为文本...它并没有真正保留Python list
的概念,因此您需要找出一种方法将列表中的users
列表转换为文本并然后返回列表的list
,以便您可以实际使用它。
有许多预制的序列化格式。这里是一些:JSON,CSV,YAML,或另一个问题,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
形状的一行文本中“重建”两个变量(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 怎么样?
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/