我正在尝试编写一个代码,要求提供电子邮件和密码(不是出于任何特定目的),并根据包含多行的csv文件进行检查。每行包含一封电子邮件和密码以及一些虚构的客户详细信息。我正在尝试编写一个接受电子邮件地址和密码(长度为5-12个字符)的代码,然后在文件中搜索包含电子邮件和密码的行,并打印整行(包括客户详细信息)。这是我到目前为止的代码(这里的一些缩进可能看起来有点奇怪,但实际上只是缩进代码块的结果):
import csv
import re
import sys
f = open('A453_datafile_4_Mat 4 Data File.csv', 'r').read()
print("Welcome to our website! To access your customer details, we first require you to sign in. ")
print("")
email = input ("Email address: ")
if re.match("\A(?P<name>[\w\-_]+)@(?P<domain>[\w\-_]+).(?P<toplevel>[\w]+)\Z",email,re.IGNORECASE):
print('')
else:
email = input("Sorry, this isn't a valid email address! Try again: ")
if re.match("\A(?P<name>[\w\-_]+)@(?P<domain>[\w\-_]+).(?P<toplevel>[\w]+)\Z",email,re.IGNORECASE):
print('')
else:
print("You have entered your email incorrectly two times. The program will now terminate." )
sys.exit() #ends program
password = input ("Password: ")
if re.match("\A(?P<name>[\w\-_]+)\Z",password,re.IGNORECASE):
print('')
else:
password = input("Sorry, this isn't a valid password! Try again: ")
if re.match("\A(?P<name>[\w\-_]+)\Z",password,re.IGNORECASE):
print('')
else:
print("You have entered your password incorrectly two times. The program will now terminate." )
sys.exit() #ends program
details = [line for line in f.split('\n') if email in line] and [line for line in f.split('\n') if password in line]
if details == []:
print("Sorry, your email or password is invalid.")
else:
print("Thank you! Here are your customer details: ")
print("")
details = str(details).strip('[]')
print(details)
我遇到了这条线的问题,因为'和'看起来不像我想要的那样:
details = [line for line in f.split('\n') if email in line] and [line for line in f.split('\n')
如果我输入了故意错误的密码(例如字母'x'),并且碰巧存在于另一行,它会打印该行,尽管它不包含电子邮件地址。
以下是此示例:
欢迎来到我们的网站!要访问您的客户详细信息,我们首先要求您登录。</ p>
电子邮件地址:ojones@coldmail.net
密码: x
谢谢!以下是您的客户详细信息:
'miguel5 @ bluebell.net,happy3,Miguel,Santos,45 Vine Avenue,Oxford,O X 7 3RF'
虽然它使用正确的密码:
欢迎来到我们的网站!要访问您的客户详细信息,我们首先要求您登录。</ p>
电子邮件地址:ojones@coldmail.net
密码:ocrabc
谢谢!以下是您的客户详细信息:
'ojones @ coldmail.net,ocrabc,Oliver,Jones,53 Vale House,Portsmouth,P03 2TD'
还有这个正则表达式,因为我无法弄清楚如何将密码长度限制为5到12个字符(我是正则表达式的新手并且没有被教过如何使用它):
if re.match("\A(?P<name>[\w\-_]+)\Z",password,re.IGNORECASE)
我怀疑修复这个问题可能主要解决了前一个问题(除非有人知道文件的内容),尽管如果可能的话,我们也会感激一些帮助。
我可能还有其他问题,但据我所知,就是这样。
我知道这个问题很长,所以感谢您花时间阅读,我们将非常感谢您的回答!
答案 0 :(得分:1)
简单回答的长问题。不要对列表连接使用布尔运算'和'。使用+,它将生成正确的列表。 '和'做什么 - 它将每个操作数转换为布尔值True / False,如果两个列表都是非空的 - 返回它们的最后一个。否则返回[](在你的情况下永远不会发生)。
答案 1 :(得分:0)
您的代码当前正在做的是循环文件两次:每个[f.split()中的行的行是一个单独的循环。第一个循环获取电子邮件匹配的行列表,第二个循环获取密码匹配的行列表。
然后,您使用'and'运算符组合两个列表。 Python允许你这样做,如果两个列表都不为空,则结果为True,否则为False。由于您尝试将操作结果与[]进行比较,因此比较将始终失败。
你正在尝试做的正确版本是有一个循环并立即检查两个条件,Python列表推导允许你这样做:
[line for line in f.split() if email in line and password in line]
但是,由于这是子字符串检查,因此当用户正确输入密码的一部分时,这将匹配,这通常不是您在检查密码时所需的密码。相反,您应该检查整个字符串:
line.startswith(email + "," + password + ",")
答案 2 :(得分:0)
这是一个在CSV文件中搜索特定字符串的简单实现:
f = open('A453_datafile_4_Mat 4 Data File.csv', 'r').read()
rows = re.split('\n', f.decode())
for index, row in enumerate(rows):
cells = row.split(',')
if ('USER_EMAIL_HERE' in cells) and ('USER_PASSWORD_HERE' in cells):
#Do stuff here
我没有对此进行测试,仅供参考。
答案 3 :(得分:0)
这是一个清理版本:
import csv
from collections import namedtuple
from itertools import repeat
import re
import sys
EMAIL_REG = re.compile("^([\w\-_]+@[\w\-_]+\.[\w]+)$", re.IGNORECASE)
PASSWORD_REG = re.compile("^([\w\-_]{5,12})$", re.IGNORECASE)
PASSWORD_CSV = 'A453_datafile_4_Mat 4 Data File.csv'
# define a User type
# (the field names should match the columns from the .csv file)
User = namedtuple("User", ["email", "password", "firstname", "lastname", "address", "city", "postalcode"])
# prettier output
User.__str__ = lambda self: "{} {}: {} ({} {}, {})".format(self.firstname, self.lastname, self.email, self.address, self.city, self.postalcode)
def all_users_from_csv(fname, **kwargs):
"""
Return an iterable of Users from the specified csv file
"""
with open(fname) as in_file:
for row in csv.reader(in_file, **kwargs):
yield User(row)
def match_user(users, email, password):
"""
Return the first user in users who matches the specified email and password;
on failure, return None
"""
for user in users:
if user.email == email and user.password == password:
return user
return None
def input_match(prompt, reg, max_tries=None):
"""
Prompt for input that matches reg;
on success, return first match group
on failure, try again (up to max_tries times, if specified)
on max_tries failures, return None
"""
if max_tries is None:
# not specified - repeat forever
tries = repeat(None)
else:
# repeat specified number of times
tries = range(max_tries)
for i in tries:
s = input(prompt)
m = reg.match(s)
if m:
return m.groups(0)
# if max_tries exceeded
return None
def do_signin():
email = input_match("Email address: ", EMAIL_REG, 2)
if email is None:
print("You did not enter a valid email address. Good-bye!")
return None
password = input_match("Password: ", PASSWORD_REG, 2)
if email is None:
print("You did not enter a valid password. Good-bye!")
return None
users = all_users_from_csv(PASSWORD_CSV)
return match_user(users, email, password)
def main():
print("Welcome to our website! To access your customer details, we first require you to sign in.\n")
user = do_signin()
if user is None:
print("Sorry, your email or password is invalid.")
else:
print("Thank you! Here are your customer details:\n")
print(user)
if __name__=="__main__":
main()
还有一些评论:
请注意,每次要匹配用户时,都必须比较(最多).csv文件中的每一行;这是缓慢而浪费的。几乎任何数据库都允许您在电子邮件和密码字段上编制索引,从而提高效率。
我将代码分成单独的函数;每个功能都很简单,只有一个特定的用途。命名常量,良好的函数名称,文档字符串和注释 - 它们都使您的程序更容易理解,测试和修改。