所以,如果我通过查看您提出的与此相关的其他两个问题(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)方法是什么@ 987654350@ 对象做。
我们需要从形状为 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 能够“知道”需要返回的对象是一个列表。