Using Python 2.7.12 I wrote a simple little script, psk_validate.py, that prompts the user for a potential password and checks if it has upper and lower-case characters, numbers, special characters, and that it has a length of at least 8 characters.From what I understand one could use the regex library to write this much more efficiently, however, I have yet to learn about regex.The program seems to work just fine, and with a program this small I think that not using regex is also just fine. I'd like any and all feedback about this program. In particular, I'd like to know if a program written this simply could be used in real-world applications. I'd also like to know if there are any logical errors and/or bugs in the program.from sys import exitdef check_upper(input):    uppers = 0     upper_list = A B C D E F G H I J K L M N O P Q R S T U V W X Y Z.split()    for char in input:        if char in upper_list:            uppers += 1    if uppers > 0:        return True    else:        return Falsedef check_lower(input):    lowers = 0    lower_list = a b c d e f g h i j k l m n o p q r s t u v w x y z.split()    for char in input:        if char in lower_list:            lowers += 1    if lowers > 0:        return True    else:        return Falsedef check_number(input):    numbers = 0    number_list = 1 2 3 4 5 6 7 8 9 0.split()    for char in input:        if char in number_list:            numbers += 1    if numbers > 0:        return True    else:        return Falsedef check_special(input):    specials = 0    special_list = ! @ $ % ^ & * ( ) _ - + = { } [ ] | \ , . > < / ? ~ ` \ ' : ;.split()    for char in input:        if char in special_list:            specials += 1    if specials > 0:        return True    else:        return Falsedef check_len(input):    if len(input) >= 8:        return True    else:        return Falsedef validate_password(input):    check_dict = {        'upper': check_upper(input),        'lower': check_lower(input),        'number': check_number(input),        'special': check_special(input),        'len' : check_len(input)    }    if check_upper(input) & check_lower(input) & check_number(input) & check_special(input) & check_len(input):        return True    else:        print Invalid password! Review below and change your password accordingly!        print        if check_dict['upper'] == False:            print Password needs at least one upper-case character.        if check_dict['lower'] == False:            print Password needs at least one lower-case character.        if check_dict['number'] == False:            print Password needs at least one number.        if check_dict['special'] == False:            print Password needs at least one special character.        if check_dict['len'] == False:            print Password needs to be at least 8 characters in length.         print                  while True:    password = raw_input(Enter desired password: )    print     if validate_password(password):        print Password meets all requirements and may be used.        print         print Exiting program...        print        exit(0)
Password Checker in Python
python;beginner;python 2.7
ConceptObligatory XKCD comic, before I begin:Enforcing password strength by requiring human-unfriendly characters is no longer considered good practice.  Nevertheless, I'll review the code as you have written it.Obvious simplificationsAny code with the pattern if bool_expr: return True; else: return False should be written simply as return bool_expr.Strings are directly iterable; there is no need to convert them into a list first, using .split().  In other words, the code would work the same if you just wrote:upper_list = ABCDEFGHIJKLMNOPQRSTUVWXYZBetter yet, you could just use string.ascii_uppercase.The uppers += 1 counting loop could be written more expressively using the sum() built-in function.  Actually, in this case, since you only care whether uppers > 0, you could just use the any() function.With those changes, your check_upper() function becomes a one-liner:def contains_upper(s):    return any(c in ascii_uppercase for c in s)I've renamed check_upper() to contains_upper() to make it clear that the function returns True or False.  Also, avoid using variable names, like input, that coincide with names of built-in functions: it could cause trouble if you ever want to use input().Code duplicationMost of your check_something() functions are identical.  You should generalize, instead of duplicating the code.from string import ascii_uppercase, ascii_lowercase, digitsdef contains(required_chars, s):    return any(c in required_chars for c in s)def contains_upper(s):    return contains(ascii_uppercase, s)def contains_lower(s):    return contains(ascii_lowercase, s)def contains_digit(s):    return contains(digits, s)def contains_special(s):    return contains(r!@$%^&*()_-+={}[]|\,.></?~`':;, s)def long_enough(s):    return len(s) >= 8Note that I've used a raw long string to help deal with the need for backslashes in the punctuation string.validate_password()The check_dict isn't doing anything for you.  You'd be no worse off with five boolean variables. You are also calling each validation function twice.The & (binary bitwise AND) operator is not quite appropriate here.  The and (boolean AND) operator would be more appropriate. Even though the results appear identical, the execution differs: the logical and allows short-circuit evaluation. Personally, I'd write it this way, gathering up a list of all of the failure messages:def validate_password(password):    VALIDATIONS = (        (contains_upper, 'Password needs at least one upper-case character.'),        (contains_lower, 'Password needs at least one lower-case character.'),        (contains_digit, 'Password needs at least one number.'),        (contains_special, 'Password needs at least one special character.'),        (long_enough, 'Password needs to be at least 8 characters in length.'),    )    failures = [        msg for validator, msg in VALIDATIONS if not validator(password)    ]    if not failures:        return True    else:        print(Invalid password! Review below and change your password accordingly!\n)        for msg in failures:            print(msg)        print('')        return FalseIf the function returns True in one place, then it would be good practice to return False instead of None in the other branch, for consistency.Free-floating codeIt is customary to put if __name__ == '__main__': around the statements in the module that are not inside a function.  That way, you could incorporate the functions into another program by doing import psk_validate without actually running this program.Calling sys.exit(0) is rarely desirable or necessary, if you structure the code properly.  Here, all you needed was a break.if __name__ == '__main__':    while True:        password = raw_input(Enter desired password: )        print()        if validate_password(password):            print(Password meets all requirements and may be used.\n)            print(Exiting program...\n)            break