Search code examples
pythonpassword-checker

str.isdigit() doesn't seem to be working in python


I'm working on a password checker that checks if the string is a valid password. I have to check if there is at least eight characters, must consist of only letters and digits and the last two characters must be digits.

It all seems to work so far other than the password.isdigit(). sometimes the password comes out valid and sometimes it doesn't. Any suggestions?

# Gets the users password
password = input('Enter a string for password: ')
# Splices the last two characters of the password
lastTwo = password[-2:]

# Checks the password if it is less than 8 characters
while len(password) < 8:
    print('The password you entered is too short.')
    print()
    password = input('Enter a string for password: ')

    # Checks the password if it is composed of letters and numbers
    while password.isalnum() == False:
        print('Your password has special characters not allowed.')
        print()
        password = input('Enter a string for password: ')

    # Checks the spice to verify they are digits
    while lastTwo.isdigit() == False:
        print('Your last two characters of your password must be digits.')
        print()
        password = input('Enter a string for password: ')

print('Your password is valid.')

Solution

  • There are a handful of issues with your provided code. Particularly, you only check the subsequent rules while len(password) < 8. If you give it a password of length 10, the rules are never checked. Additionally, you don't update the lastTwo with each new password attempted

    One way to fix this would be to replace your several while statements with if...elif..elif...else... wrapped in an overall while statement, as follows:

    # Gets the users password
    password = input('Enter a string for password: ')
    
    while True:
        # Checks the password if it is less than 8 characters
        if len(password) < 8:
            print('The password you entered is too short.')
        # Checks the password if it is composed of letters and numbers
        elif not password.isalnum():
            print('Your password has special characters not allowed.')
        # Checks the spice to verify they are digits
        elif not password[:-2].isdigit():
            print('Your last two characters of your password must be digits.')
        else:
            # we only get here when all rules are True
            break
    
        print()
        password = input('Enter a string for password: ')
    
    print('Your password is valid.')
    

    This should work as you intended it. But while we're at it, why not tell the user every rule their password has broken? From a UI point of view, it helps to keep the user informed.

    If we store an information message alongside whether the relevant rule has been met, we can quickly work out all of the rules that have been broken, like so:

    valid_password = False
    
    while not valid_password:
        # Get a password
        password = input('\nEnter a string for password: ')
        # applies all checks
        checks = {
            '- end in two digits': password[-2].isdigit(),
            '- not contain any special characters': password.isalnum(),
            '- be over 8 characters long': len(password) > 8
        }
        # if all values in the dictionary are true, the password is valid.
        if all(checks.values()):
            valid_password = True
        # otherwise, return the rules violated
        else:
            print('This password is not valid. Passwords must:\n{}'.format(
                '\n'.join([k for k, v in checks.items() if not v])))
    
    print('Your password is valid.')