使用csv文件在python中检索和检查密码

时间:2014-12-19 17:09:59

标签: python regex email csv line

我正在尝试编写一个代码,要求提供电子邮件和密码(不是出于任何特定目的),并根据包含多行的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)

我怀疑修复这个问题可能主要解决了前一个问题(除非有人知道文件的内容),尽管如果可能的话,我们也会感激一些帮助。

我可能还有其他问题,但据我所知,就是这样。

我知道这个问题很长,所以感谢您花时间阅读,我们将非常感谢您的回答!

4 个答案:

答案 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()

还有一些评论:

  1. 请注意,每次要匹配用户时,都必须比较(最多).csv文件中的每一行;这是缓慢而浪费的。几乎任何数据库都允许您在电子邮件和密码字段上编制索引,从而提高效率。

  2. 我将代码分成单独的函数;每个功能都很简单,只有一个特定的用途。命名常量,良好的函数名称,文档字符串和注释 - 它们都使您的程序更容易理解,测试和修改。