python password checker: numbers and symbols - python

I'm new to python and I'm having a problem. I need to check a password on its upper, lower, numbers and symbols. It needs 1 of each class and the whole password needs to be longer then 6 characters. I have upper and lower case so far. raw_input inputs as a string so how can I then check for numbers and symbols in that string?
My code so far:
p = raw_input(("plz enter a password to check it's strength"))
if len (p) <= 6:
if p.isupper() or p.islower() or int(p):
print"This is a weak password "
elif len(p) > 6 and len(p) <26:
if p.isupper() or p.islower() or isdigit():
print "wea2k"
else:
print "good"
So what I need to know is how to check the input for numbers and symbols.

Try taking the requirements one at a time.
has_upper = False
for char in p:
if char.isupper():
has_upper = True
break
Repeat this for lower case and digits.
For special characters, use the same type of loop, but change the if to something like this:
if not (char.isupper() or char.islower() or char.isdigit()):
At the end, if all four flags are true, then you have a strong password; otherwise, it's weak.
Can you finish the coding from there?
Just so you know, there are ways to code this that are far more "Pythonic" -- that use the language's style much better. For instance:
has_upper = reduce(lambda a, b: a or b.isupper(), [_ for _ in p], False)
... replaces the entire 5-line block that I gave you.

Try this:
p = raw_input(("plz enter a password to check it's strength"))
upper_case = 0
lower_case = 0
number = 0
symbol = 0
for i in p:
if i.isupper():
upper_case += 1
elif i.islower():
lower_case += 1
elif i.isdigit():
number += 1
else:
symbol += 1
if len (p) <= 6:
print"This is a weak password "
elif upper_case > 0 and lower_case > 0 and number > 0 and symbol > 0:
print "Good"
else:
print "Too Weak"

Related

Why is Python exiting the while loop without fullfilling all the conditions?

I am coding a password checker for an assignment. Here are the requirements:
At least 2 letter between [a-z] and 1 letter between [A-Z]. At least 1 number between [0-9]. At least 1 character from [?$##]. Minimum length 10 characters. Maximum length 14 characters. Moreover, in case of invalid password, the program should keep on asking for new password unless it validates it successfully.
For some odd reason, my code ignores the while loop conditions and jumps out of it after completing the for loop. What am I doing wrong and how could I fix this? Any help is appreciated!
import string
#password
password = input("Enter a password that has at least two lower case letter, one upper case letter, one number between one and nine, and one of the following characters: '?$##.'")
#requirements
ll = list(string.ascii_lowercase)
ul = list(string.ascii_uppercase)
nums = ["1","2","3","4","5","6","7","8","9"]
char = ["?","$","#","#"]
#counters
llcounter = 0
ulcounter = 0
numscounter = 0
charcounter = 0
while llcounter < 2 or ulcounter < 1 or numscounter < 1 or charcounter < 1:
if len(password) > 10 and len(password) < 14:
for x in password:
if x in ll:
llcounter += 1
elif x in ul:
ulcounter += 1
elif x in nums:
numscounter += 1
elif x in char:
charcounter += 1
else:
password = input("Your password has not met the requirements, please try another one.")
well that is because your nested loop logic is flawed. it will keep iterating through the for loop and never checks the while loop conditions. you want the for loop iteration on the outside and break outside when the while conditions are met
for ...:
while ...:
...
break
password = input( ... first prompt ... )
while True:
set all counters = 0
for x in password:
if x in ll:
...etc, just like above...
if llcounter >= 2 and ulcounter and numscounter and charcounter:
break
password = input ( ... second prompt ... )
You need to look up Validate input. You have interleaved steps of your logic. The basic structure is:
valid_pwd = False
while not valid_pwd:
password = input("Enter a password ...")
# Make *one* pass to validate the password.
# Count each type of character;
...
# Also check the length
length_valid = 10 < len(password) < 14
chars_valid = (
ll_count >= 2 and
lu_count >= 1 and
...
)
valid = length_valid and chars_valid
if not valid:
print("Invalid password")
Does that get you going?
When coding in Python you should always try to find the most Pythonic way to implement your idea, namely by making the most of the language's potential to write concise, clear and functional code.
In your case you have redundant code in several places, especially that while loop with so many counters is pretty confusing.
Also, in order to maintain an active input session for the user, you should put the prompt inside the while loop, otherwise the password will always be the same entered for the first (and only) time making the loop itself rather pointless.
For example, here's how you might implement this password check. I commented on the code to try to explain what it's actually doing.
import string
ll = list(string.ascii_lowercase)
ul = list(string.ascii_uppercase)
nums = list(string.digits)[1:] # List of digits except 0
sc = ["?","$","#","#"]
# while True meaning keep prompting forever until password requisites are satisfied.
# This can be changed with a counter to exit the loop after a certain number of attempts.
while True:
password = input("Enter a password that has blablabla...") # Prompt the user at every iteration of the loop.
# The following if block merges all your conditions in the same place avoiding hyper-nested
# conditions that are always confusing and kind of ugly.
# The conditions are based on list comprehension
# (see py docs, since its a super cool feature that is the ultimate tool for conciseness).
if (len([char for char in password if char in ll]) >=2 and
[char for char in password if char in ul] != [] and
[char for char in password if char in nums] != [] and
[char for char in password if char in sc] != []):
print(f" Your new password is: {password}")
break # break interrupts the endless loop as soon as a valid password is entered
else:
print("Your password has not met the requirements, please try another one.")

How do I count the number of capital letters using a while loop

s = input()
i = 0
while i < len(s) and (s[i]) < "A" or "Z" < s([i]):
print(i)
I keep getting this wrong and I'm not sure what to do. I Do not want to use a for loop just a while loop. Thank you
You can do it by many ways.
If I were you I will do it using isupper() and sum() generator,
s = input("Type something...")
print(sum(1 for c in s if c.isupper()))
Using while as you asked,
s = input("Type something...")
i = 0
capital = 0
while i < len(s):
if s[i].isupper():
capital+=1
i = i + 1
print(capital)
Your while loop is currently written such that it will terminate at the first lowercase letter. You need the loop to go over the entire string, but keep count of uppercase letters as it goes.
s = input()
i = 0
c = 0
while i < len(s):
if "A" <= s[i] <= "Z":
c = c + 1 # c only goes up on capital letters
i = i + 1 # i goes up on every letter
print(i, c)
print(f"Capital letters: {c}")
An easier method is to use the sum function along with isupper:
s = input()
print(f"Capital letters: {sum(c.isupper() for c in s)}")
You are using the while for both the limit and the counting which won't work.
You have to use the while for the limit and an if for the counting:
s = input()
i = 0
count = 0
while i < len(s):
print(i)
if "A" <= s[i] <= "Z":
count += 1
i = i + 1
print(f'Capitals in "{s}" = {count}')
However, this code is very complicated and better is the answer from #AlwaysSunny or the comment from #Samwise
def Capital(In):
return sum([l.isupper() for l in In])
print(Capital(input()))
Try use this:
text = input()
count=0
for letter in text:
if letter == letter.upper():
count+=1
print(letter, end=" ")
print(count-1)
I hope I have explained clearly)

How can I resolve maximum recursion depth error

I'm generating a random password with a desired length. I want it to have at least 2 uppercase letters, 2 lowercase letters, 2 digits and 2 special characters. I've tried multiple things, but every time I get this recursion depth error.
Can anybody tell me what I've done wrong?
list_lower =['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']
list_upper = ['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']
list_digit = [1,2,3,4,5,6,7,8,9,0]
def generatePassword(desiredLength: int) -> str:
x = 0
password = ""
for x in range (desiredLength):
password = password + chr(random.randint(33,126))
list(password)
list_password = list(password)
times_lower = 0
times_upper = 0
times_digit = 0
times_special = 0
for character in list_password:
if character in list_lower:
times_lower += 1
elif character in list_upper:
times_upper += 1
elif character in list_digit:
times_digit += 1
else:
times_special +=1
if times_lower >= 2 and times_upper >= 2 and times_digit >= 2 and times_special >= 2:
return password
else:
return generatePassword(desiredLength)
generatePassword(7)
I get the error in line 30 which makes the function recursive.
Calling generatePassword(7) will never generate a password with 2 of each of 4 distinct categories.
You don't need recursion at all.
def generatePassword(desiredLength: int) -> str:
while True:
password = ""
for x in range (desiredLength):
password = password + chr(random.randint(33,126))
times_lower = 0
times_upper = 0
times_digit = 0
times_special = 0
for character in password:
if character in list_lower:
times_lower += 1
elif character in list_upper:
times_upper += 1
elif character in list_digit:
times_digit += 1
else:
times_special +=1
if times_lower >= 2 and times_upper >= 2 and times_digit >= 2 and times_special >= 2:
return password
else
print ("Rejecting ", password)
That will loop forever if asked to generate a password of length 7 or less. We can improve that by checking the desired length first
if desiredLength < 8:
raise ArgumentError("Cannot generate passwords shorter than 8 characters")
times_digit will never be >= 2 because it tests stings (e.g. "2" against the integers in your list, (e.g. 2) change your list_digit to
list_digit = ["1","2","3","4","5","6","7","8","9","0"]
and try again.
By the way this could be done much simpler and doensn't need a recursive function.
If you are generating passwords, it's important that you generate ones that actually have enough randomness to not be predictable.
Random string generation with upper case letters and digits in Python
Has a great breakdown of how to generate a password that's truly random:
''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(N))
(adding "special characters" and "lowercase characters" omitted to preserve the existing code)
I know that this is a somewhat oblique answer (i.e. it does not answer the question directly), so here's a potential solution if you still need the "it must contain these types of characters" (even though that would actually reduce security):
import random
import string
from collections import Counter
def gen(N):
return ''.join(random.SystemRandom().choice(string.ascii_letters + string.digits + string.punctuation) for _ in range(N))
while True:
pw = gen(8)
counts = Counter(pw)
upper = lower = digit = special = 0
for (letter, count) in counts.items():
if (letter in string.ascii_lowercase):
lower += 1
elif (letter in string.ascii_uppercase):
upper += 1
elif (letter in string.digits):
digit += 1
else:
special += 1
pass
if (lower > 1 and upper > 1 and digit > 1 and special > 1):
print("password is {}".format(pw))
break
print("failed password: {}".format(pw))

how to check repeating Vowels

I'm pretty new to python and I'm having trouble with my
if then else statements and I only get is "no repeating vowels" which mean my rep_vowel is still returning 0
so the program rules are as follows.
if no vowel appears next to itself (e.g. hello), then print:
no vowel repeats
if exactly one vowel is repeated in sequence at least once (e.g. committee) then print a message that indicates which vowel repeats:
only vowel e repeats
if more than one vowel repeats (e.g. green door) then print:
more than one vowel repeats
ignore upper case - lower case differences: assume all the input is always lowercase
answer = input("Enter a string: ")
rep_vowel = 0
i = 0
length_Answer = len(answer)
next_string = 1
curChar = answer[0+rep_vowel]
for i in range(0,length_Answer):
if answer[0 + i] in ["a","e","i","o","u"]:
i =+ 1
next_string = answer[0+i+i]
if next_string == answer:
rep_vowel =+ 1
if rep_vowel == 0:
print("no repeating vowles")
elif rep_vowel > 1:
print("more than 1 repeating vowels")
else:
print ("the letter "+ str(curChar) +" repeats")
You have a few mistakes so i'll try to address several of them:
You do a lot of [0 + something] indexing, which is useless, since 0 + something always equals to something, so yo should just do indexing with [something]
Changing the value of i with i += 1 is bad because you are already increasing it as part of the loop
All you have to do to find a match is simply match the current letter to the next one, if both are the same and they are also vowels, you've found a match.
You are initializing unnecessary variables such as i = 0 only to have them overridden in the next lines
Adding all of those together:
answer = input("Enter a string: ")
vowels = "aeiou"
repeats = [] # this list will hold all repeats of vowels
for i in range(len(answer) - 1): # i'll explain the -1 part at the end
if answer[i] in vowels and answer[i] == answer[i + 1]:
repeats.append(answer[i])
if len(repeats) == 0:
print("no repeating vowles")
elif len(repeats) > 1:
print("more than 1 repeating vowels")
else:
print("the letter " + repeats[0] + " repeats")
This still doesn't take every possible input into account, but it should get you started on a final solution (or perhaps that's enough). For example, input of teest will give the correct result but the input of teeest doesn't (depends on your definition of correct).
About the len(answer-1) range, that's only to make sure we don't go out of bounds when doing answer[i + 1], so we're stopping on the next to last letter instead.
Firstly, you have to indent your code.
to say if (condition) then do print('hello') you write it this way:
if condition:
print('hello')
Secondly, you are using i =+ 1 which is the same as i=1
I think you meant i +=1 which is i = i+1
Finally, I suggest this code:
answer = input("Enter a string: ")
vowel_repeated_count = 0
length_Answer = len(answer)
i=0
while (i <length_Answer-1):
#we check if it's a vowel
if answer[i] in ["a","e","i","o","u"]:
#we check if it's followed by the same vowel
if answer[i+1] == answer[i]:
#increment the vowel_repeated_count
vowel_repeated_count +=1
#we save the vowel for the display
vowel = answer[i]
#we skip the other same repeated vowels
#example: abceeed, we skip the third e
while (answer[i] == vowel and i < length_Answer-1):
i +=1
#we add this incrementation because we're in a while loop
i +=1
if vowel_repeated_count == 0:
print("no repeating vowles")
elif vowel_repeated_count == 1:
print("the letter "+ str(vowel) +" repeats")
else:
print ("more than 1 repeating vowels")
You have some logical errors. It's time consuming to edit that. You can try this, I have modified your code. Hope it will work for you. I have commented beside every important line.
answer = input("Enter a string: ")
is_found = {} #a dictionary that will hold information about how many times a vowel found,initially all are 0
is_found["a"]=0
is_found["e"] = 0
is_found['i']=0
is_found['o']=0
is_found['u']=0
vowels =["a","e","i","o","u"]
for i in range(0,len(answer)):
if answer[i] in vowels:
is_found[answer[i]] = is_found[answer[i]]+1 # if a vowel found then increase its counter
repeated=0 #let 0 repeated vowel
previously_repeated=False #to trace whether there is a previously repeated character found
curChar=None
for key,value in is_found.items(): #iterate over dictionary
if previously_repeated and value>1: #if a vowel found and previously we have another repeated vowel.
repeated=2
elif previously_repeated==False and value>1: # we don't have previously repeated vowel but current vowel is repeated
curChar=key
previously_repeated=True
repeated=1
if repeated== 0:
print("no repeating vowles")
elif repeated> 1:
print("more than 1 repeating vowels")
else:
print ("the letter "+ str(curChar) +" repeats")
There is no need to increment your counter i. In your for loop, it will increment itself each time it goes through the for loop. Also, you need a variable to keep track of how many times the vowel repeats.
answer = input("Enter a string: ")
rep_vowel = 0
length_Answer = len(answer)
vowelList=["a","e","i","o","u"]
vowelRepeated = []
#this will go from i=0 to length_Answer-1
for i in range(length_Answer):
if (answer[i] in vowelList) and (answer[i+1] in vowelList):
if (answer[i] == answer[i+1]):
vowelRepeated.append(answer[i])
repVowel += 1
if rep_vowel==0:
print("no repeating vowels")
elif rep_vowel==1:
print("only one vowel repeated:")
print(vowelRepeated)
else:
print("multiple vowels repeated:")
print(vowelRepeated)
for such counting, I will prefer to use a dictionary to keep the counting number. Your code has been modified for your reference
answer = input("Enter a string: ")
length_Answer = len(answer)
count = dict()
for i in range(length_Answer):
if answer[i] in ["a","e","i","o","u"]:
if answer[i+1] == answer[i]:
if answer[i] in count:
count[answer[i]] += 1
else:
count[answer[i]] = 1
rep_vowel = len(count)
if rep_vowel == 0:
print("no repeating vowles")
elif rep_vowel > 1:
print("more than 1 repeating vowels")
else:
for k in count:
vowel = k
print("the letter " + vowel + " repeats")
You have a few issues with your solution :
1) You never use curChar, i'm guessing you wanted to enter the next_string value into it after the '==' statement.
2) You compare your next_string to answer, this will always be a false statement.
3) Also no need to use [0+i], [i] is good enough
Basically what you want to do is this flow :
1) Read current char
2) Compare to next char
3) If equal put into a different variable
4) If happens again raise a flag
Optional solution :
vowel_list = ["a","e","i","o","u"]
recuring_vowel_boolean_list = [answer[index]==answer[index+1] and answer[index] in vowel_list for index in range(len(answer)-1)]
if not any(recuring_vowel_boolean_list ):
print("no repeating vowels")
elif (recuring_vowel_boolean_list.count(True) > 1):
print("More then 1 repeating vowels")
else:
print("The letter {} repeats".format(answer[recuring_vowel_boolean_list.index(True)]))

Python - Finding all non alpha-numeric characters in a string

I'm designing a system that allows users to input a string, and the strength of the string to be determined by the amount of non alphanumeric characters. Points should be awarded like so: +1 for every non-alnum character to a maximum of 3 non-alnum characters.
def non_alnum_2(total,pwd):
count = 0
lid = 3
number = 0
if pwd[count].isalnum():
if True:
print "Nope"
if False:
print "Good job"
count = count + 1
number += 1
if number > lid:
number = lid
return number
total = 0
number = 0
pwd = raw_input("What is your password? ")
non_alnum_2(total, pwd)
print total
total += number
I've only just started coding, so I'm sorry if this seems like a very junior question.
You can simply try:
bonus = min(sum(not c.isalnum() for c in pwd), 3)
If you want to count the number of non-alpha strings you could say
def strength(string):
'''Computes and returns the strength of the string'''
count = 0
# check each character in the string
for char in string:
# increment by 1 if it's non-alphanumeric
if not char.isalpha():
count += 1
# Take whichever is smaller
return min(3, count)
print (strength("test123"))
There are multiple problems with this code.
First, if True: is always true, so the "Nope" will always happen, and if False: is never true, so none of that stuff will ever happen. I think you wanted this:
if pwd[count].isalnum():
print "Nope"
else:
print "Good job"
count = count + 1
number += 1
Also, I think you want to increment count always, not just if it's a symbol, so:
if pwd[count].isalnum():
print "Nope"
else:
print "Good job"
number += 1
count = count + 1
Meanwhile, you need some kind of loop if you want this to happen over and over. For example:
while count < len(pwd):
if pwd[count].isalnum():
# etc.
However, you really don't need to maintain count yourself and keep doing pwd[count]; you can use a for loop for this:
for ch in pwd:
if ch.isalnum():
# etc.
Meanwhile, while you do return a value from the end of the function, you don't do anything with that returned value when you call the function. What you need is:
number = non_alnum_2(total, pwd)
Also, there's no reason to pass total to non_alnum_2 here. In fact, it doesn't do anything useful at all.
So, putting it all together:
def non_alnum_2(pwd):
lid = 3
number = 0
for ch in pwd:
if ch.isalnum():
print "Nope"
else:
print "Good job"
number += 1
if number > lid:
number = lid
return number
pwd = raw_input("What is your password? ")
number = non_alnum_2(pwd)
print number
def non_alnum(s):
temp=[]
for i in s:
if i.isalnum():
continue
else:
temp.append(i)
if temp==[]:
print("The string doesn't contain any non_alphanumeric chars")
else:
print("The string contains non_alphanumeric chars: ",temp)
str1="ABCDEFabcdef123450"
str2="ABCDEF;abcdef'1234!50"
str3="*&%#!}{"
non_alnum(str1)
non_alnum(str2)
non_alnum(str3)

Categories