Checking multiple conditions for a "password" - python

I'm trying to write code that can check if an input contains;
At least 8 letters, whereas at least 1 of those is a number (0-9)
Contains an upper and lower case character
I keep getting stuck in a "inputs password, returns true, and input password again, exit" single loop..
Fairly new at programming, doing my first semester atm so all help would be appreciated!
This is my program so far
def is_valid():
valid = 0
password = input("Password: ")
for ele in password:
if ele.isupper and ele.islower and ele.isdigit and len(password) > 7:
return "True"
else:
return "False"
print(is_valid())
is_valid()
I tried moving the print inside the function, as I think it is intended, by then It won't print..

for ele in password:
if ele.isupper and ele.islower and ele.isdigit and len(password) > 7:
return "True"
else:
return "False"
This code has several problems.
First, you're referring to the ele.isupper function, but because you don't have parentheses (), you're not calling the function. So the code is basically asking "Does ele.isupper exist"? Well yes, it is a function, and it exists, so the if condition is true.
Use ele.isupper() instead of ele.isupper.
Second, even if you fix that problem (and also the same problem for ele.islower and ele.isdigit), there's no way that one letter will be uppercase AND lowercase AND a digit.
Third, the return statement makes the function exit immediately, so your loop will only look at the first letter. Instead of doing that, you want to loop over all the letters, and move the return statement to after the loop.
I think you were actually looking for code like this:
uc = 0
lc = 0
digits = 0
for ele in password:
if ele.isupper():
uc += 1
elif ele.islower():
lc += 1
elif ele.isdigit():
digits += 1
if uc > 1 and lc > 1 and digits > 1 and len(password) > 7:
return "True"
else:
return "False"

There are many ways to do this. But first I will clarify some mistakes.
First, when you write ele.isupper you are not calling the function, for that you must put the parenthesis: ele.isupper().
Secondly, your loop is looping through each letter of the password and in the case of solving the previous bug you would find that the condition would never be fulfilled since a character cannot be all things at the same time.
I leave you an example of how you can solve these problems, as I said, there are many ways to do it but I present you one that is not complex and uses the basics. Also, if the password is incorrect, ask for it again on the screen.
def is_valid():
valid = [0, 0, 0]
password = input("Password: ")
for ele in password:
if len(password) < 8:
break
elif ele.isupper() and valid[0] == 0:
valid[0] = 1
elif ele.islower() and valid[1] == 0:
valid[1] = 1
elif ele.isdigit() and valid[2] == 0:
valid[2] = 1
if sum(valid) < 3:
print('False')
is_valid()
else:
print('True')
is_valid()
Output:
Password: hello
False
Password: Hello
False
Password: Hello World
False
Password: Hello World 1
True
The code first checks if the length is correct, if it is not, it does not make any further checks.
If this condition is met it continues and as conditions are met, one of the variables in the valid list is incremented. You can do this with a number instead of a list, but if you want to specify what has gone wrong you can access each value in the list to check it or say that n conditions have failed, for example:
if valid[1] == 0:
print('There must be at least one lower character').

There are a couple of problems in your code.
Reaching return statement exits the loop and the function itself, returning the value. So you are just checking first letter and the immediately finish the loop.
valid = 0 seems to be never used.
Last instruction if your function print(is_valid()) would also have no effect.
One possible straightforward solution to your problem would be to set a number of different flags for things you want to check, ant then once you find them, set te proper value for the flags. Like this:
def is_valid():
password = input("Password: ")
has_upper = False
has_digit = False
has_lower = False
has_good_length = False
for ele in password:
if ele.isupper():
has_upper = True
if ele.islower():
has_lower = True
if ele.isdigit():
has_digit = True
if len(password) > 7:
has_good_length = True
if has_upper and has_lower and has_digit and has_good_length:
return True
return False
print(is_valid())

You should also check for characters that are neither letters nor digits (according to the rules stated in the question) - e.g., punctuation.
How about using a bit mask?
def is_valid(pwd):
state = 0
if len(pwd) >= 8:
for c in pwd:
if c.isdigit():
state |= 1
elif c.islower():
state |= 2
elif c.isupper():
state |= 4
else:
state |= 8
return state == 7
password = input('Password: ')
print(is_valid(password))

You're going element-wise in a loop on your password, rather than considering the whole thing together. You want something like:
def is_valid():
password = input("Password: ")
if not any(el.isupper() for el in password):
return False
if not any(el.islower() for el in password):
return False
if not any(el.isdigit() for el in password):
return False
if len(password) < 8:
return False
return True
is_valid()

for ele in password will iterate through the characters in the user's input.
your if statement doesnt make sense. ele.isupper and ele.islower will never be true at the same time.
if statement needs work. make booleans for each condition you want to validate and set them to true individually is you see the required elements.

Related

How do I get a function to identify a variable I've identified

My program is trying to create a program that identifies a program that includes 3 functions: 1 to identify the length, 1 to make sure they're are not any spaces and 1 that makes sure that the program checks that you're using at least 1 number and letter. I basically have almost everything that I want, I'm just not understanding how to put them together and work cohesively.
In the passlength function, I get the correct outcome if I were to add "password = input("Enter password: ")" at the beginning of the line. However, I'm trying to do that within the main function. Then it should collapse in that function to check whether or not you have the correct amount of characters. No less than 6 characters, but no more than 15.
In the next function, I'm trying to make sure no spaces are in the password, however no matter what I do it keeps rendering false.
I've tried the same thing as above with the "isalpha" and "isdigit" functions as well. However, I'm unsure how it would check from 0 to 15 make sure that at least 1 digit and 1 alphabetical letter are used.
But my overall concern is how to use a variable in my main function then transfer that don't do my subfunctions for results, then using an if statement loop it back in case your password isn't safe.
def passLength():
password = input("Enter password: ")
if len(password) > 5 and len(password) < 15:
print("Password Length - Confirmed")
else:
print("Password length - Invalid, please try again")
passLength()
def passSpace():
password = input("Enter password: ")
passwordSpace = password.isspace()
print(passwordSpace)
def main():
password = input("Enter password: ")
passLength()
Here is the kind of organization you need. The validation functions just do validation. It is up to the caller to decide what to do with the information.
def passLength(password):
return 5 < len(password) < 15
def passSpace(password):
return ' ' not in password
def main():
while True:
password = input("Enter password: ")
if not passLength(password):
print("Too short or too long. Try again.")
elif not passSpace(password):
print("No spaces allowed. Try again.")
else:
print( "Success" )
break
main()

comparing user input and list created by text file using in operator always returns false

Creating an access code program. I created a list and placed the file in it.
The output is: ['Cameron', 'Cameron', 'sudocode', 'Sudocode'...] ect. That part is fine.
I have tried using many different methods, mainly the 'in' operator to get boolean value of True. Never happens. I type in 'Cameron' and I get back false. Here is the code.
`
with open("kwaccess.txt") as file:
keyword1 = file.read().splitlines()
keyword_accesslist = [x.rstrip() for x in keyword1]
print(keyword_accesslist)
output is: ['Cameron', 'cameron', 'sudocode', 'Sudocode', 'Python or python']
for attempt in keyword_accesslist:
print(verify1)`
# Another attempt
if attempt in keyword_accesslist:
verify1 == True
else:
verify1 == False
If I type in Cameron, which is in the list for certain or any of the keywords, I get back False 5 times (for the 5 elements in the list, then it moves on to next part of code. Everything else works. Even the random number generator that I use the 'in' operator to compare with the user input and works perfect. It's the file into a list that has the compare jacked up. What am I missing...how do you compare a list element to the user string input with the 'in' operator.
I've gotten this error a few times during this long stretch of 'Denying' further coding day :)
TypeError: 'in ' requires string as left operand, not list...not currently, but along the way
Good luck Master coders.
HERE IS THE CODE:
def code_generator(string):
test = str(string) + str(randint(200,2000))
return test
def list_random_true():
codenumber = [number for number in range(200,2000)]
return codenumber
def access_code(attempt):
with open("kwaccess.txt") as file:
keyword1 = file.read().splitlines()
keyword_accesslist = [x.rstrip() for x in keyword1]
print(keyword_accesslist) # output is: ['Cameron', 'cameron', 'sudocode', 'Sudocode', 'Python or python']
##This is my PROBLEM AREA, can't rotate through the elements in list and compare against attempt
verify1 = False
for x in range(len(keyword_accesslist)):
verify1 = attempt == str(keyword_accesslist[x])
if verify1 == True:
x = 1
for x in range(3):
print("Verifying...")
time.sleep(3)
break
else:
x += 1
input("Access Denied. Please re-enter password. ")
if x == 3:
print("Your account has been locked. Please contact Admin Services.")
exit()
else:
pass
numbercheck = str(list_random_true()) # Each number in own element to check
for number in numbercheck:
verify2 = number in attempt
if verify2 == True: # Second Security Attemp
print("Access Granted")
break
else:
pass
BEGINNING OF PROGRAM
try:
compare = input("Please enter Secret Code. ")
except EOFError as e:
pass
attempt = code_generator(compare)
access_code(attempt)
Ok I checked out your code. With what you have, I do not understand what you are doing. verify1 = attempt == keyword_accesslist[x] will always return false as attempt is attempt is the user input but with some random digits appended to it, which is never the first element of keyword_accesslist. In addition, are you trying to check each word in keyword_accesslist and see if the attempt is equal or just the first element? Because you only iterate once every x, then if the check is wrong it will print "access denied" THEN check the next keyword_accesslist.
With some guesses, I think this is similiar to what you want:
verify1 = False
tries = 0
while tries < 3:
for password in keyword_accesslist:
verify1 = attempt == password
if verify1:
for x in range(3):
print("Verifying...")
time.sleep(3)
break
if not verify1:
tries += 1
attempt = input("Access Denied. Please re-enter password. ")
if tries == 3:
print("Your account has been locked. Please contact Admin Services.")
exit()
It's not the best, but I have changed the loop so that it probably does what you want it to do. It uses a nested loop to check for the password and the outer while loop to keep track of tries. I've attempted to use your logic, but I don't understand some of your other functions.
This feels like a debugging problem and not suited for stackoverflow, but I hope that you recieved the help you need.

How to use != sign correctly in if/else clause?

Problem: I'm trying to invoke ask_user() again if the user inputs words != 'encrypt' or 'decrypt', but the same error message appears when the input IS correct.
def ask_user():
while True:
mode = input("Would you like to encrypt or decrypt: ")
if mode != 'encrypt' or mode != 'decrypt':
print("Please retry; you must type lowercase. \n")
ask_user()
else:
message = input("Enter your message: ")
It seems that using more than one != statements on same line doesn't work as I'd imagined:
# test to support above observ.
for n in range(4):
if n != 2 or n != 3:
print('me')
else:
print(n)
How should I change the code to fix this problem?
Your problem is that you are using or instead of and.
If you think about how the code is interpreted:
Let's say that mode="encrypt". Step by step:
mode != 'encrypt' evaluates to false. All good so far.
mode != 'decrypt', however, evaluates to true. This is a problem.
The final expression sent to the if will be: false or true. This, finally, evaluates to true, causing the if block to be entered.
Changing it to and means that both of invalid modes will have to be checked true for the block to be entered.
n != 2 or n != 3 will always be true. If n is 2 then it's not 3. All other values are not 2.
You intended n != 2 and n != 3.
You need to use and, not or. Because n will never be equal to both 3 and 4, the if statement that incorporates or will always resolve to True

For loops concatenated – beginner python exercise

Hi everyone I’m writing because I’m stuck with an exercise in which I should only use for loops and if/else statements. I found a way but practically I’m iterating the same block of code four times and I’m really looking for a way to automate it.
I know that probably this is not the best way to solve the exercise but now I’m not looking for the most efficient way (I already found on the solutions of the exercise), I’m asking you how can I use for to iterate the block of code
The exercise tells me to create a program that takes an IP address from the keyboard and validates that it can be interpreted as a valid IP address.
An IP address consists of 4 numbers, separated from each other with a full stop. Each number can have no more than 3 digits. (Examples: 127.0.0.1)
Important
This challenge is intended to practise for loops, and if/else statements, so although it would probably be written for real using regular expressions we don't want you to use them here even if you know what they are.
This is what I made:
# ipAddress = input("please enter an ipAddress: ")
ipAddress = "192.168.7.7" #test ip address
# check if number of dots is 3
numberOfDot = 0
for char in ipAddress:
if char == '.':
numberOfDot += 1
totNumbOfDot = numberOfDot # output of this section is totNumberOfDot, to be checked at the end
if totNumbOfDot != 3:
print("You inserted a wrong ip address")
# first number check # THIS IS THE BLOCK OF CODE I WANT TO
number1 = '' # ITERATE WITH FOR IF POSSIBLE
for char in ipAddress:
if char in "0123456789":
number1 += char
if char == '.':
break
if 1 <= len(number1) <= 3:
print("First number: OK")
else:
print("First number: Fail")
digitN1 = len(number1) + 1
print(number1)
# second number check
numberMinus2 = ipAddress[digitN1:]
number2 = ''
for char in numberMinus2:
if char in "0123456789":
number2 += char
if char == '.':
break
if 1 <= len(number2) <= 3:
print("Second number: OK")
else:
print("Second number: Fail")
digitN2 = len(number2) + digitN1 +1
print(number2)
# third number check
numberMinus3 = ipAddress[digitN2:]
number3 = ''
for char in numberMinus3:
if char in "0123456789":
number3 += char
if char == '.':
break
if 1 <= len(number3) <= 3:
print("Third number: OK")
else:
print("Third number: Fail")
digitN3 = len(number3) + digitN2 + 1
print(number3)
# fourth number check
numberMinus4 = ipAddress[digitN3:]
number4 = ''
for char in numberMinus4:
if char in "0123456789":
number4 += char
if char == '.':
break
if 0 < len(number4) <= 3:
print("Fourth number: OK")
else:
print("Fourth number: Fail")
digitN4 = len(number4) + digitN3 + 1
print(number4)
I would also say, split() is the way to go. Your question was if there was a way to use your logic and still not have to repeat code 4 times. To achieve that you could do something like this:
numberOfDot=0
number=""
for char in ip+'.':
if char=='.':
numberOfDot+=1
if len(number) in [1,2,3]:
print("number %d OK"%numberOfDot)
else:
print("number %d not OK"%numberOfDot)
print(number)
number=""
elif char in '1234567890':
number+=char
else:
print("character not valid")
if numberOfDot!=4:
print("you inserted a wrong ip")
As i said, i would also recommend using split() - this is just to try and provide an answer closer to your question. Also please note that this code (same as yours) will mark ip adresses containing letters, not only numbers, as OK.
Well, you have to ask yourself the right question: "can I do better?". Please always do that. Yes, in fact, you can. The code that deals with numbers validation between dots is essentially the same. So you should split the string on dots and use for loop to validate each group:
for str in ipAddress.split("."):
your validation here
how about that? split the string at the dots . and check if between the dots there are numbers in the valid range (that would also accept '255.255.255.255')
def valid(ipaddress):
# we need 3 dots; otherwise this is no ipaddress.
if not ipaddress.count('.') == 3:
return False
# check what is before, between and after the dots
for byte in ipaddress.split('.'):
# if byte can not be interpreted as an integer -> no good!
try:
i = int(byte)
except ValueError:
return False
# now check if byte is in the valid range
if i < 0:
return False
if i > 255:
return False
return True
print(valid(ipaddress='192.168.7.7')) # -> True
print(valid(ipaddress='.168.7.7')) # -> False
print(valid(ipaddress='721.168.7.7')) # -> False

Python Password Checker Help Debugging

So in my computer programming class we've been tasked with making the generic password strength checker, mine works and checks the length correctly but for whatever reason the 2nd part doesn't work properly and I can't figure out why.
password = input("Please enter a password between 6 - 12 characters long: ")
while len(password) in range(6, 13) == False:
if len(password) < 6:
print("Password too low!")
password = input("Please enter a password between 6 - 12 characters long: ")
elif len(password) > 12:
print("Password too high!")
password = input("Please enter a password between 6 - 12 characters long: ")
Upper = 0
Lower = 0
Numerical = 0
for char in password:
if char == char.isupper():
Upper = Upper + 1
elif char == char.islower():
Lower = Lower + 1
elif char == char.isnumeric():
Numerical = Numerical + 1
Strength = int(Upper + Lower + Numerical)
if Strength == 1:
print("Password is weak!")
elif Strength == 2:
print("Password is medium!")
elif Strength == 3:
print("Password is strong!")
Any help would be greatly appreciated, I browsed other similar problems but with something specific it's kind of difficult.
EDIT: Removing the parenthesis from my while loop will do nothing, it works the same anyway. The in range part makes no difference, I still get the error:
Traceback (most recent call last):
File "C:\Users\Owen\Desktop\Password Checker.py", line 21, in
for char in password():
There are a lot of little issues you can fix with this section of code so I can't really tell you what is producing the improper output.
1) as Ken stated:
len(password) != range(6, 12) will always return true. This is because you are comparing an int to a list.
range(6, 12) gives you [6, 7, 8, 9, 10, 11] so the length of the password can never be equal to that statement. However, if you use len(password) in range(6, 12) the length of the password is compared to each value in the list until there is a match (if there is one). One more thing, using range(a, b) only includes numbers from a to b-1. So you really want:len(password) in range(6, 13)
2) The logic of the while loop should change with changes from my first point.
If len(password) in range(6, 13) evaluates to True, then the while statement won't loop and you will move on to the next section. You can delete the else section and change your elif to else.
3) You can get rid of LengthLow and LengthHigh since you aren't using them anywhere.
4) password is a string so you can't call it with the () operator. Your for loop should be for char in password:
5) Use char.isupper(), char.islower(), or char.isnumeric() to check if they are numeric values
6) You don't need to store Upper, Lower, and Numerical separately since you are just adding them together at the end anyways. You can actually accomplish this with a one liner if you are familiar with list comprehensions
strength = sum([1 if c.isupper() or c.islower() or c.isnumeric else 0 for c in password])
Although, it seems to me that this is all the same as c.isalnum() for alphanumeric. So write,
strength = sum([1 if c.isalnum() else 0 for c in password])
7) I don't know anything about password strength calculation, but I think special characters should be considered as well. In that case c.isalnum() won't be the magic all in one that it is in your current code.
There may be more bugs that I haven't noticed, but that should definitely get you on your way to fixing the problem.
ero1ca's answer explains many of the issues.
As for the last part of the code not working, that is because you loop through every char in the password, and increment based on what that character is. With a mandated length > 3, your conditional statements at the end wont cover the password!
below is a revised version of the code.
password = input("Please enter a password between 6 - 12 characters long: ")
while not len(password) in range(6, 13):
if len(password) < 6:
print ("Password too low!")
else:
print ("Password to high!")
password = input("Please enter a password between 6 - 12 characters long: ")
Upper = 0
Lower = 0
Numerical = 0
if any(x.isupper() for x in password):
Upper = 1
if any(x.islower() for x in password):
Lower = 1
if any(x.isdigit() for x in password):
Numerical = 1
Strength =int(Upper + Lower + Numerical)
if Strength == 1:
print ("Password is weak!")
elif Strength == 2:
print ("Password is medium!")
else:
print ("Password is strong!")
Use raw_input instead of input() for python 2.7
Edit Holy Necro! My mistake lads!

Categories