I am trying to return the password entered by a user if it matches a-z,A-Z,0-9,_,- otherwise a ValueError will be executed within a try clause. Here is my line of code that doesn't seem to be working as it allows just about anything like (?.,##$%^*)
return re.match('^[A-Za-z0-9_-]*$',password)
With the Kleene closure, you allow an empty string as a correct password. You can use the + special character to match one repetitions of the valid characters:
def validate(password):
match = re.match('^[a-z0-9_-]+$', password, re.I)
if match is not None:
return password
else:
raise ValueError
Outline
Using sets and set-subtraction is likely a simpler solution.
Code
from string import ascii_letters, digits
PASSWORD_SET = set(ascii_letters + digits + "_-")
def has_only_password_letters(candidate):
return not(set(candidate) - PASSWORD_SET)
or:
def has_only_password_letters(candidate):
return all(c in PASSWORD_SET for c in candidate)
Tests
>>> def test_password(password):
... if has_only_password_letters(password):
... print "Okay: ", password
... else:
... print "Nuh-uh: ", password
...
>>> test_password("asdasd123123")
Okay: asdasd123123
>>> test_password("asdasd123123!!!")
Nuh-uh: asdasd123123!!!
Here is a non-regex solution using isalnum:
for c in password:
if not (c.isalnum() or c in ['_', '-']):
raise ValueError('Invalid character in password')
Related
for c in password:
if not any(c in password for c in symbols):
return False
if not any(c.isdigit() for c in password):
return False
if not any(c.islower() for c in password):
return False
if not any(c.isupper() for c in password):
return False
return
print(password)
f = open("demofile2.txt", "a")
f.write(password + "\n")
f.close()
You want to avoid doing extra work when verifying that your password satisfies all requirements. In my example, I've looked at each character only once and am performing the required checks every time I look at a different character.
In the example you provided, you're actually verifying that every character meets your requirements for every character in the password O(N*N) - this is not recommended.
Lastly, make sure you understand what the password requirements are. It seems like your logic is incorrect when trying to verify that a character is both lowercase and uppercase simultaneously.
edit: The author clarified in comments that in order for a password to be valid, that password must have at least:
one symbol
one digit
one lowercase character
one uppercase character
has_symbol = False
has_digit = False
has_lower = False
has_upper = False
for c in password:
if has_symbol and has_digit and has_lower and has_upper:
break
elif c in symbols:
has_symbol = True
elif c.isdigit():
has_digit = True
elif c.islower():
has_lower = True
elif c.isupper():
has_upper = True
if has_symbol and has_digit and has_lower and has_upper:
print(password)
f = open("demofile2.txt", "a")
f.write(password + "\n")
f.close()
else:
return False
you should take care about time complexity by avoiding unnecessary
loops.
this will help you:
from string import punctuation
def check_pass(password):
return all([any(filter(str.islower, password)),
any(filter(str.isupper, password)),
any(filter(str.isdigit, password)),
any(filter(lambda x: x in punctuation, password))
]
)
def save_password(password):
if check_pass(password):
with open("demofile2.txt", "a") as f:
f.write(password)
print(password)
else:
print('Not Accepted!')
# Test
save_password('1#cA')
I am coding a password analyzer with several properties, one being that the user's password must not have special characters (##$%^&*) except for ! (exclamation mark) and _ (underscore). I am using the .isalnum() method for this purpose but I cannot figure out a way to make it so it doesn't return True when ! or _ is used WITH any other special character (ex: Python$ returns False but Python_ returns True).
Here is my code:
password = input('Enter a password: ')
if not password.isalnum():
if '_' in password or '!' in password:
pass
else:
print('Your password must not include any special characters or symbols!')
The most intuitive way is to check every character.
if not all(c.isalnum() or c in '_!' for c in password):
print('Your password must not include any special characters or symbols!')
This is one way. replace the ! and _ withe empty string and then check with isalnum().
password = input('Enter a password: ')
pwd = password.replace('_', '').replace('!', '')
if pwd.isalnum() and ('_' in password or '!' in password):
pass
else:
print('Your password must not include any special characters or symbols!')
Another way of checking it is by using regex
import re
x = input('Enter a password: ')
t = re.fullmatch('[A-Za-z0-9_!]+', x)
if not t:
print('Your password must not include any special characters or symbols!')
def is_pass_ok(password):
if password.replace('_', '').replace('!','').isalnum():
return True
return False
password = input('Enter a password: ')
if not is_pass_ok(password):
print('Your password must not include any special characters or symbols!')
By removing all allowed special characters, i.e. _ and !:
password.replace('_', '').replace('!','')
it remains only to check for alphanumeric characters (.isalnum()).
I am supposed to write a script with the following criteria:
Write a function called validatePassword that takes a password string as a parameter and returns true or false. The function should only return true if:
The password is at least 8 characters
The password contains at least one number
The password contains at least one upper case letter. Hint: use the isupper() string function.
The password contains a symbol one of the symbols !##$%^&*()+=
I have this so far:
def validatePassword(pswd):
if len(pswd)> 8:
return True
else:
return False
for char in pswd:
if char in '01234567890':
return True
else:
return False
for char in pswd:
if char in '!##$%^&*()_+=':
return True
else:
return False
for char in pswd:
if char.isupper and char .islower:
return True
else:
return False
return True
while False:
print("There was an error with your password")
print (validatePassword(Herseuclds))
I know that print (validatePassword(Herseuclds)) has a syntax error because I am missing the variable but I just don't get how to do this.
def validatePassword(pswd):
if len(pswd) < 8:
return False
number_in_password = False
for char in pswd:
if char in '012356789':
number_in_password = True
if not number_in_password:
return False
symbol_in_password = False
for char in pswd:
if char in '!##$%^&*()_+=':
symbol_in_password = True
if not symbol_in_password:
return False
uppercase_in_password = False
for char in pswd:
if char.isupper():
uppercase_in_password = True
if not uppercase_in_password:
return False
#this only happens if nothing above has disqualified the password
return True
print (validatePassword("herseuc"))
print (validatePassword("herseuclds"))
print (validatePassword("herseuclds!"))
print (validatePassword("herseuclds!123"))
print (validatePassword("herseuclds!123A"))
The main issue with your code is in the last line.
print (validatePassword(Herseuclds))
Right now, the interpreter thinks Herseuclds is a variable, and not a string. If Herseuclds is the password, and not a variable describing the password, then you need quotes around it to make it a string literal.
print (validatePassword("Herseuclds"))
You obviously haven't defined a variable called Herseuclds anywhere in your program, but the program thinks Herseuclds is a variable and not a string, so it throws the error.
Best of luck, and happy coding!
First issue is that you are passing an undeclared variable to your function. See silentphoenix's answer for details.
Secondly, your program only check to see if AT LEAST ONE condition is met, not all.
If a password is 8 characters long, it will return true even if the password doesn't satisfy the other requirements.
I am not going to write your code for you, but I can pseudocode the issue:
def validatePassword(pswd):
if len(pswd) < 8:
return False
# if there isn't a number:
return False
# if there isn't a symbol:
return False
# if there isn't an upper and lowercase:
return False
return True
while True:
print("There was an error with your password")
print (validatePassword("Herseuclds"))
sidenote: watch your indentation :)
Since you can use is.upper() you can also utilize is.digit() to check for numbers instead of having to write down actual digits.
Another thing to speed it up, since they all have to be done at the same time, you can check if the password validates those requirements in one line with any()
def validatePassword(pswd):
l = []
if len(pswd)> 8:
for char in pswd:
l.append(char)
if any(l for x in l if x.isdigit()) and any(l for x in l if x.isupper()) and any(l for x in l if x in '!##$%^&*()_+='):
print('Success')
else:
print('Try again')
while True:
a = input('What is your password?')
validatePassword(a)
At the beginning there's an minimum check to see if the lengeth is greater than 8. If it is, the word gets broken up into a list. This allows any() to be used and checked against the remainding requirements.
def valid_password(password):
return (
# The password is at least 8 characters
len(password) >= 8 and
# The password contains at least one number
any(c in "0123456789" for c in password) and
# The password contains at least one upper case letter
any(c.isupper() for c in password) and
# The password contains a symbol one of the symbols !##$%^&*()+=
any(c in "!##$%^&*()+=" for c in password))
Example:
from getpass import getpass
while not valid_password(getpass('Enter password: ')):
print('invalid password. Try again')
Homework exercise:
Checking whether a text is a palindrome should also ignore punctuation, spaces and case. For example, "Rise to vote, sir." is also a palindrome but our current program doesn't say it is. Can you improve the above program to recognize this palindrome?
origin code:
def reverse(text):
return text[::-1]
def is_palindrome(text):
return text == reverse(text)
something = input('Enter text: ')
if (is_palindrome(something)):
print("Yes, it is a palindrome")
else:
print("No, it is not a palindrome")
my try:
import re
def reverse(text):
global words
words = text.split()
return words[::-1]
def is_palindrome(text):
return words==reverse(text)
something = input('Enter text: ')
if (is_palindrome(something)):
print("Yes, it is a palindrome")
else:
print("No, it is not a palindrome")
Error:
Enter text: jfldj
Traceback (most recent call last):
File "/Users/apple/PycharmProjects/Problem Solving/user_input.py", line 13, in <module>
print("Yes, it is a palindrome")
File "/Users/apple/PycharmProjects/Problem Solving/user_input.py", line 10, in is_palindrome
NameError: name 'words' is not defined
How should I change my code?
Latest code:
import string
def remove_punctuations(word):
return "".join(i.lower() for i in word if i not in string.ascii_letters)
def reverse(text):
return text[::-1]
def is_palindrome(text):
text = remove_punctuations(text)
return text == reverse(text)
something = input('Enter text: ')
if (is_palindrome(something)):
print("Yes, it is a palindrome"
else:
print("No, it is not a palindrome")
No matter what I input, output is Yes.
Enter text: hggjkgkkkk
Yes, it is a palindrome
What's wrong?
To ignore the punctuations, spaces and case of the given text you need to define a function remove_punctuations() which takes a word as parameter and returns a word with all lower case characters, remove punctuation marks and removed spaces.
To remove the unwanted characters we need to iterate over the given text, if the current character falls in strings.ascii_letters , then generate the character converting it to lower caps using str.lower() method. Finally using "".join() method to concatenate the generated str elements.
import string
def remove_punctuations(word):
return "".join(i.lower() for i in word if i in string.ascii_letters)
def reverse(text):
return text[::-1]
def is_palindrome(text):
text = remove_punctuations(text)
return text==reverse(text)
something = "Rise to vote, sir."
if (is_palindrome(something)):
print("Yes, it is a palindrome")
else:
print("No, it is not a palindrome")
Since the hint says to use a tuple with forbidden punctuation marks, I created the following variant:
forbidden = (' ', ',', "'", '?', '!', '.', '’')
def reverse(text):
return text[::-1]
def cleaning(text):
clean_text = ''
for item in text:
if item not in forbidden:
clean_text += item
return clean_text
def is_palindrome(text):
lower_text = cleaning(text.lower())
return lower_text == reverse(lower_text)
example = input('Enter something: ')
if is_palindrome(example):
print("Yes, it is a palindrome")
else:
print("No, it is not a palindrome")
The cleaning function checks each character for belonging to a tuple of forbidden characters, if not, then concatenates it to the clean_text string
I started studying for python 2 days before so that is what i come up with.
It is not so much advanced but works like a charm. :D
It is pretty straight forward what i do there. I just make a tuple with the "legal" letters (abc=). Then I define a function that 1st change all letters to lower case and then checks every character in the string with the "legal" letters. Then after this "filtering" the rawtext contains only the "legal" ones. Then the 2nd function just reverses the results of the 1st one. Compare and da da..!
# Palindrome recognize
abc='abcdefghijklmnopqrstuvwxyz'
def rawtext(text):
rawtext=''
text=text.lower()
for j in text[::1]:
for i in abc[::1]:
if j==i:
rawtext=rawtext+j
return rawtext
def reverse(text):
rev= rawtext(text)[::-1]
return rev
text=str(input('Write text:'))
if reverse(text)==rawtext:
print('The text is palindrome')
else:
print('The text is not a palindrome')
from itertools import izip_longest
def is_palindrome(s):
l = len(s)
fi = (i for i in xrange(l) if s[i].isalpha())
bi = (i for i in xrange(l-1, -1, -1) if s[i].isalpha())
for f, b in izip_longest(fi, bi):
if f >= b: return True
if s[f].lower() != s[b].lower(): return False
return True
Hope that helps
The task is to get a user to input a password then, using recursion, make sure it has no vowels in it. If it does then let the user re-enter the password. This is what i have so far:
def passwordCheck(pwd):
"""checks if pwd has any vowels in it."""#doc string
vowels = 'aeiou'#specifies the characters that aren't allowed
if pwd == '':
return 0
elif pwd == None:
return None#Shouldn't be necessary but just in case
elif pwd[0] not in vowels:#checks that the 1st(0th) character is not a vowel
return passwordCheck(pwd[1:])#gets rid of the 1st(0th) character and starts again
elif pwd[0] in vowels:#checks if the 1st(0th) character is a vowel
return 1#if it is, stops the function calls and returns a value
password = str(input('Please enter a password with no vowels in it: '))#asks user to input their new password
x = passwordCheck(password)#checks the password is valid, i.e. no vowels
while x == 1:#when the password entered contains a vowel
print('\nSorry, that is not a valid password.\nYour password cannot contain any vowels.')#tells the user why their password is invalid
password = str(input('\nPlease enter a different password: '))#gives the user a chance to re-enter their password
x = passwordCheck(password)#checks to make sure the new password is valid
print('\nCongratulations, you have entered a valid password!')#tells the user if their desired password is valid
print('\nYou are now able to log on to the system with these credentials.')#could've been included on the previous line but looks neater here
I know this is probably not the most pythonic way of doing it but it works for me in most cases. I'd love to hear a better way but ideally someone can help in the same style. I don't want to just copy someones code without understanding it.
The question i have is dealing with the case where the user enters no password at all. The first if statement:
if pwd == '':
return 0
I thought it just dealt with the case when the string had been fully recursed through, i.e. no vowels, but after a minutes inspection it's obvious this applies to no password as well.
I had also tried using:
if pwd == None:
return something
Now i'm thinking the problem could be because i said:
password = str(input('######'))
but i've fiddled with that as well and still can't can't seem to make that work either! I've tried google and searching stackoverflow but no luck so if anyone has any ideas/solution they think might be helpful I'd be very grateful to hear them. Thank you very much.
My main question is:
How can i differentiate between a string that's empty because it's been recursed through and the user inputting nothing?
Solved.
ended up using
def passwordValid(pwd):
if len(pwd)>0 and passwordCheck(pwd)==0:
return pwd
else: return 'Fail'
password = str(input('Please enter a password with no vowels in it: '))#asks user to input their new password
y = passwordValid(password)#checks the password is valid, i.e. no vowels
while y == 'Fail':#when the password entered contains a vowel
print('\nSorry, that is not a valid password.\nYour password cannot contain any vowels or be empty.')#tells the user why their password is invalid
password = str(input('\nPlease enter a different password: '))#gives the user a chance to re-enter their password
y = passwordValid(password)#checks to make sure the new password is valid
print('\nCongratulations, you have entered a valid password!')#tells the user if their desired password is valid
print('\nYou are now able to log on to the system with these credentials.')#could've been included on the previous line but looks neater here
Thank you Wayne Werner for fixing the title and the main question.
This problem can be broken down into (at least) three distinct subproblems:
check whether a string contains vowels
check whether a string is a valid password (length > X and has vowels)
get a password from the user
Your code should reflect this structure. You could therefore use the following function layout:
def has_vowels(string):
if not string: # check for empty string
return False # empty strings never have vowels
# TODO we have a non-empty string at this point and can use recursion
def is_valid_password(string):
return len(string) > 0 and not has_vowels(string)
def request_password():
while True: # use an endless loop here, we don't won't to repeat
# the "input" statement. We could also change this to
# something like `for i in range(3)` to allow only a limited
# number of tries.
passwd = input('Please enter a password with no vowels in it: ')
# TODO check if input is valid, if yes, return, if no, print an error
Don't attempt to solve both problems with a single method. You have two ditinct critera: no vowels; minimum length.
def isPasswordValid(pwd):
return len(pwd) > 4 and not passwordCheck(password)
x = isPasswordValid(password)
...
You could solve this with recursion by adding another parameter which indicates how many characters have been looped through, but that is clumsy and offers no real benefit.
You can't differentiate between an empty string and an empty string. You can however set the variable to None, or to a string like "__no_string_entered_yet". That said, I don't see why you would need to, see the other answers.
I believe this does what your question asks for:
Not allow an empty password (different than a "blank" password?)
Not allow vowels in the password
I opted not use if/elif/else in favor of structuring it so that valid characters "fall through"
def pwd_check(s):
vowels = 'aeiou'
if len(s) == 0: return False # This is only valid in the first iteration
if s[0] in vowels: return False
if len(s) == 1: return True # Success: a 1 character pwd with no vowels
return pwd_check(s[1:])
I thought about putting checks in to make sure that a string like ' ' was not passed in, but I didn't see that explicitly asked for. pwd_check(password.strip()) solves this problem.
Here's how I like to do.
For the fun, I added conditions of minimum and maximum lengths for the password:
def passwordCheck(pwd,vowels = 'aeiou',minimum=5,maximum=12):
if pwd == '':
return 0,None,None
elif pwd[0] in vowels:
return -1,None,None
else:
y = passwordCheck(pwd[1:])[0]
if y==-1:
return -1,None,None
else:
return y + 1,minimum,maximum
mess = 'Please enter a password with no vowels in it: '
while True:
x,miin,maax = passwordCheckstr(input(mess))
if x==-1:
mess = ('\nSorry, that is not a valid password.\n'
'Your password cannot contain any vowels.\n'
'Please enter a different password: ')
elif x==0:
mess = ('\nSorry, you must enter a password.\n'
'Please do enter a password: ')
elif x<miin:
mess = ('\nSorry, the password must have at least %d characters.\n'
'The string you entered has %d characters.\n'
'Please, enter a new longer password: ' % (miin,x))
elif x>maax:
mess = ('\nSorry, the password must have at most %d characters.\n'
'The string you entered has %d characters.\n'
'Please, enter a new shorter password: ' % (maax,x))
else:
print ('\nCongratulations, you have entered a valid password!\n'
'\nYou are now able to log on to the system with these '
'credentials.')
break
edit
Another kind of algorithm.
I wasn't satisfied to return such tuple as -1,None,None
def check_password(forbidden,minimum,maximum):
def passwordCheck(pwd,cnt=0,forbid = forbidden,
miin=minimum,maax = maximum):
# cnt is the number of preceding turns of recursion
# that have been already executed.
if pwd == '':
if cnt==0:
# cnt==0 means that it's the first turn of recursion
# since pwd is '', it means no entry has been done
return 0
elif cnt<miin:
return -3
elif cnt>maax:
return -2
elif pwd[0] in forbid:
return -1
else:
if cnt in (-3,-2,-1):
return cnt
else:
return passwordCheck( pwd[1:] , cnt+1 )
mess = 'Please enter a password with no vowels in it: '
while True:
x = str(raw_input(mess)).strip()
y = passwordCheck(x)
if y==0: # inexistent string
mess = ('\nSorry, you must enter a password.\n'
'Please do enter a password: ')
elif y==-1: # string contains a vowel
mess = ('\nSorry, that is not a valid password.\n'
'Your password cannot contain any vowels.\n'
'Please enter a different password: ')
elif y==-2: # string too long
mess = ('\nSorry, the password must have at most %d characters.\n'
'The string you entered has %d characters.\n'
'Please, enter a new shorter password: ' % (maximum,len(x)))
elif y==-3: # string too short
mess = ('\nSorry, the password must have at least %d characters.\n'
'The string you entered has %d characters.\n'
'Please, enter a new longer password: ' % (minimum,len(x)))
else: # success
print ('\nCongratulations, you have entered a valid password!\n'
'You are now able to log on to the system with these credentials.')
break
# EXECUTION
check_password('aeiou',5,12)