I've been trying to create a really simple login screen on python for fun. Somewhere else in the program I have it save the entered username and password as a str (in dict format) on an external file. I can get it to check if the key-username- is correct but i cant find a way to make it check if the password entered is the password linked with the key -the value- I might of worded this weirdly but does any one have any idea how?
def login():
clear()
gap()
loginu = input("ENTER YOUR USERNAME:")
gap()
file = open("usernamesf.txt","r")
usernra = file.read()
usernr = usernra.replace("'","")
usernw = '"{' + usernr + '}"'
print (usernw)
usernwl = ast.literal_eval(usernw)
print (usernwl)
if loginu in usernwl:
gap()
loginp = input("ENTER YOUR PASSWORD:")
loginpc = usernw[loginu]
if loginp in loginpc:
print ("yay")
else:
gap()
print ("NO USERNAME FOUND...")
time.sleep(0.5)
gap()
signu = input("Would you like to sign up?")
if signu in ['yes','y','Y','Yes',' yes',' Yes',' y',' Y']:
sign()
else:
menu()
I would first recommend that you use the json library to parse your file - it is able to convert python dictionaries to string and vice versa, which is really useful.
To convert dict to str:
json.dumps(dictionary)
To convert str to dict: json.loads(string)
With this, to read the dictionary from the file, it is simply:
import json
with open("usernamesf.txt") as f:
user_dictionary = json.loads(f.read())
if loginu in user_dictionary:
password = input("ENTER YOUR PASSWORD")
if user_dictionary[username] == password:
# success
Notice how i used the with statement here for the file - this ensures that the file is properly closed by python after you are done with it - that is, after you exit the with block. You can read more about this in the official python documentation on file I/O here: https://docs.python.org/2/tutorial/inputoutput.html#methods-of-file-objects
Related
I made a login/signup program where the user must type in credentials in order to make an account or enter.
But I have two problems though, one is inside the function 'sign_up()' if the user is attempting to make a pre-existing account it should print the 'This username is taken' statement, but that's not the case. It prints a Value Error called 'I/O operation on closed file' instead.
Then the second problem is, it doesn't print the credentials in a designated file called 'LOG-IN_DATA', it's basically where you store it.
Anyway here is the code:
from class1 import Credentials
def sign_up():
choose_username_data = input("Choose a UserName: ")
choose_password_data = input("Choose your password: ")
Credentials(choose_username_data, choose_password_data)
data = open('LOG-IN_DATA', 'a+')
if choose_username_data not in data:
data.write(str(Credentials))
data.write('\n')
welcome()
data.close()
if choose_username_data in data:
print("This username is taken!")
sign_up()
data.close()
def log_in():
username_data = input("Enter your username: ")
password_data = input("Enter your password: ")
data = open('LOG-IN_DATA', 'r')
data.read()
data.close()
if username_data and password_data in data:
welcome()
elif username_data and password_data not in data:
print("Username or Password does not match or not recognized.")
log_in()
def welcome():
print("Welcome! You made it in!")
def login_or_signup():
signup_var = ('Signup', 'SignUp', 'signup')
login_var = ('Login', 'LogIn', 'login')
prompt_user = input("Welcome! Would you like to Login or Signup?: ")
if prompt_user in login_var:
log_in()
elif prompt_user in signup_var:
sign_up()
else:
print("\nChoose 'Login' or 'Signup'")
login_or_signup()
login_or_signup()
Sorry if the code is too long. I just want problems and potential ones to be eliminated as far as I am concerned.
Anyways thank you in advance!
Try using with statements when manipulating files. It handles flush and close automatically even when errors occur.
For example:
with open("path", 'r') as f:
content = f.read()
instead of:
f = open("path", 'r')
content = f.read()
f.close()
The problem with this line if choose_username_data in data: is that before, you also used data. The cursor in the file is at the end of this file. So when you ask a second time without setting the cursor back to the start of the file, it read nothing. That's why the 2nd statement never evaluates true.
With everything I told you, the sign_up function can be written:
def sign_up():
loop = True
while loop:
choose_username_data = input("Choose a username: ")
choose_password_data = input("Choose your password: ")
creds = Credentials(choose_username_data, choose_password_data)
with open('LOG-IN_DATA', 'a+') as data:
content = data.read()
if choose_username_data not in content:
data.write(str(creds)+'\n')
welcome()
loop = False
# if choose_username_data in content:
else:
print("This username is taken!")
There's one last feature I want for my bank account system.
I want it to check if a username has already been saved to the text file database. If the username already exists, then it should tell the user that they can't have that name option. If not, then they would be able to use it.
The rest of my code works as it should, it's just the fcat that I can't append/update my text file properly and see if usernames already exist in the text file database.
import sys
users = {}
status = ""
# Functions ---------------------------------------------------------------------------------------------------------
# Select either account creation or login
def displayMenu():
global status
status = input("Are you a registered user? \n1 - Yes \n2 - No \nQ - Quit \n")
if status == '1':
oldUser()
elif status == '2':
newUser()
else:
print("Unknown input error, exiting . . . .")
sys.exit(0)
return status
# Account creation
def newUser():
global createLogin
createLogin = input("Create login name: ")
if createLogin in users: # check if login name exists
print ("\nLogin name already exists!\n")
else:
createPassw = input("Create password: ")
users[createLogin] = createPassw # add login and password
print("\nAccount created!\n")
#---- Storing the username in a txt file
file = open("accountfile.txt", "a")
file.write(createLogin)
file.write("\n")
file.close()
oldUser()
# Account login
def oldUser():
global login
login = input("Enter login name: ")
passw = input("Enter password: ")
# check if user exists and login matches password
if login in users and users[login] == passw:
file = open("accountfile.txt", "r")
for text in file: ######## This is where I'm trying to compare username duplicates
if text in file == createLogin:
print("Username already exists!")
print("\nLogin successful!\n")
Bank_Account()
else:
print("\nUser doesn't exist or wrong password!\n")
print("Restarting. Please enter details correctly . . . . .")
sys.exit(0)
class Bank_Account:
def __init__(self):
self.balance=0
response = ''
def deposit(self):
try:
amount=float(input("Enter amount to be Deposited: "))
except ValueError:
print("Enter digits only")
else:
self.balance += amount
print("\n Amount Deposited:",amount)
def withdraw(self):
try:
amount = float(input("Enter amount to be Withdrawn: "))
if self.balance>=amount:
self.balance-=amount
print("\n You Withdrew:", amount)
except ValueError:
print("Enter digits only")
s.withdraw()
else:
print("\n ")
def display(self):
print("\n Remaining Balance=",self.balance)
displayMenu()
s = Bank_Account()
# Calling functions with that class object
s.deposit()
s.withdraw()
s.display()
So it looks you are are writing the user input in the file accountfile.txt. So after a few users log in it might look something like:
$ cat accountfile.txt
mike
sarah
morgan
lee
The section of your code in question is here:
file = open("accountfile.txt", "r")
for text in file:
if text in file == createLogin:
print("Username already exists!")
This particular part is probably not doing what you think it's doing:
if text in file == createLogin
...
if text in file is returning either True or False.
...
So the line above is essentially saying
if False == createLogin
or
if True == createLogin
I believe what you want to do is check if a name is in accountfile.txt. The smallest change you could make to your code in order to achieve that would be
file = open("accountfile.txt", "r")
for text in file:
if text.strip() == createLogin: # .strip() will clean up the \n
print("Username already exists!")
This line:
if text in file == createLogin: is where you are making a mistake. The line is essentially saying:
"(if the text is in the file) compare the result of that check with the string createLogin".
i.e. if (True/False) == createLogin, which is always false because the True/False boolean primitives are never equal to any string (if it actually runs, i have not tested to see if an exception will be thrown).
what you should do is this
for text in file: # get one line of text
if createLogin == text.strip(): # compare the line with the user input string
print("Username already exists!")
break
.strip() removes any leading or trailing spaces in the database stored name (in this case the line break character \n used to denote the end of a line in the file. break ends the loop prematurely cos your lookup is complete since you found what you were looking for, and it would be an unnecessary to continue comparing the user input with other strings, imagine the txt had 1000 names and the 1st name was a match, the user would see the error printed but the program would continue running for the rest of the 999 tries, making it seem sluggish and waste unnecessary CPU cycles.
The database is still case sensitive however which may or may not be desired depending on your requirements. For case insensitivity you could do the following:
for text in file: # get one line of text
if createLogin.lower() == text.strip().lower(): # compare the line with the user input string
print("Username already exists!")
break
.lower() makes both strings into lower case strings and then checks if they are the same, eliminating the case sensitivity.
Instead of writing to the text file, try pickling the database.
This will save a representation of the object that you can easily load back into your program.
import pickle
users = {}
users["Ash"] = "password"
pickle.dump(users, open("users.p", "wb"))
loaded_users = pickle.load(open("users.p", "rb"))
print(loaded_users)
A more advanced solution may also be to check out a relational database, such as [sqlite3][1]
Here is my code -
#Using pickle
#using pickle with dictionaries
import pickle
checkDeets = True
passWrong = "You have entered incorrect details, please try again"
x = input("want to enter data? - ")
if x == "yes":
file = open("data.pickle" , "wb")
signUpU = input("enter user - ") #Later used as sign in details
signUpP = input("enter pass - ") # as above
ID_in = {signUpU : signUpP} #Is meant to store the two user details
pickle.dump(ID_in, file)
file.close()
y = input("want to log in? ")
if y == "yes":
file = open("data.pickle" , "rb")
ID_out = pickle.load(file)
while checkDeets == True:
signInU = input("enter username - ")
signInP = input("enter pass - ")
if signInU in ID_out:
if signInP == ID_out[signInU][0]:
print("Login accepted")
checkDeets = False
else:
print("1")
print(passWrong)
else:
print("2")
print(passWrong)
Here is my inputs -
want to enter data? - yes
enter user - user123
enter pass - pass123
want to log in? no
>>> x = open("data.pickle" , "rb")
>>> x
<_io.BufferedReader name='data.pickle'>
this last part is where i get confused, as it seems that my dictionary data is not being saved. And this is causing my to have other errors in my log in part of my code, where the user details are not recognized.
New to pickling, sorry if there are any obvious mistakes. Using python 3
open() returns a file object, your repl output is expected. If you want to see what the data inside of it contains pass it to pickle.load() like so:
want to enter data? - yes
enter user - foo
enter pass - bar
want to log in? no
>>> import pickle
>>> pickle.load(open("data.pickle" , "rb"))
{'foo': 'bar'}
>>>
And you can see your data is being saved and loaded without issue. The second part of your code doesn't work because of this:
if signInP == ID_out[signInU][0]:
ID_out[signInU] is a string, the password, so ID_out[signInU][0] is the first character of that password. If the password is "bar" this line compares "bar" (the string we're checking against the stored password) to "b" (the first letter of the stored password) and obviously these are not the same string. Just drop the [0] and this code should do want you're going for.
I have made a program on python 3.5 which you can find out the password linked to a username, make a new password for an existing user and add a new user and password to the dictionary then pickles it so every time I load the program all the usernames and passwords will be there.
The error that comes up is after you create the pickle file(after running it for the first time) then on line 6 the error
AttributeError: Can't get attribute 'NewPass' on <module '__main__' (built-in)>
occurs.
Here is my script:
import sys
import pickle
import os
if os.path.exists("branston.p"):
LOGG = pickle.load(open('branston.p', 'rb'))
else:
LOGG = {'Sam': ('CHRIST')}
def Find():
Username = input("Say a Username.")
print (LOGG[Username])
def NewPass():
Username = Input("Enter your username.")
Newpass = input("Enter your new password")
if NewPass == input("Confirm password"):
LOGG[Username] = (NewPass)
def NewEntry():
NewUser = input("Enter your new username.")
Newpass = input("Enter your new password.")
LOGG[NewUser] = (NewPass)
loop = True
while loop == True:
function = input("Say what you want me to do.'Find', 'NewPass', 'NewEntry', 'Stop'.")
if function == ("Find"):
Find()
elif function == ("NewPass"):
NewPass()
elif function == ("NewEntry"):
NewEntry()
elif function == ("Stop"):
f = open('branston.p', 'wb')
pickle.dump(LOGG, f)
f.close()
sys.exit()
Any help would be appreciated. Thanks!
When you do this
LOGG[NewUser] = (NewPass)
You are assigning the function NewPass to your dict entry. You are probably intending to assign the password string and therefore it should be.
LOGG[NewUser] = Newpass
Note: Parenthesis are superfluous. I'd also suggest avoiding using upper case letters as the first character of your variable names, as otherwise it is easy to confuse variable and function names.
I am trying to create an AI-like chatbot, and one of its features is a login. I have used the login code before and it works fine, but I am now encountering difficulties with the code dealing with the hashing of the passwords. Here's the code:
import hashlib
...
register = input ("Are you a new user? (y/n) >")
password_file = 'passwords.txt'
if register.lower() == "y":
newusername = input ("What do you want your username to be? >")
newpassword = input ("What do you want your password to be? >")
newpassword = hashlib.sha224(newpassword).hexdigest()
file = open(password_file, "a")
file.write("%s,%s\n" % (newusername, newpassword))
file.close()
elif register.lower() == ("n"):
username = input ("What is your username? >")
password = input ("What is your password? >")
password = hashlib.sha224(password).hexdigest()
print ("Loading...")
with open(password_file) as f:
for line in f:
real_username, real_password = line.strip('\n').split(',')
if username == real_username and password == real_password:
success = True
print ("Login successful!")
#Put stuff here! KKC
if not success:
print("Incorrect login details.")
And here's the result I'm getting:
Traceback (most recent call last):
File "<FOLDERSYSTEM>/main.py", line 36, in <module>
newpassword = hashlib.sha224(newpassword).hexdigest()
TypeError: Unicode-objects must be encoded before hashing
I have looked up the encoding I think I should be using (latin-1) and found the required syntax, added that in and I still receive the same result.
Hashing works on bytes. str objects contain Unicode text, not bytes, so you must encode first. Pick an encoding that a) can handle all codepoints you are likely to encounter, and perhaps b) other systems that produce the same hashes also use.
If you are the only user of the hashes, then just pick UTF-8; it can handle all of Unicode and is most efficient for western texts:
newpassword = hashlib.sha224(newpassword.encode('utf8')).hexdigest()
The return value from hash.hexdigest() is a Unicode str value, so you are safe to compare that with the str values you read from your file.