Pickle module in Python and text files - python

I have recently asked a question and received an answer that I must 'pickle' my code. As a beginner, I have no idea how to do that.
This was my code:
users = []
users.append([username, password])
usersFile = open("users.txt","w+")
for users in users:
usersFile.write("%s" % users)
usersFile.close()
def loginFunction():
userEntry = ""
foundName = 0
while userEntry == "":
userEntry = raw_input("Enter your username: ")
usersFile = open("users.txt", "r")
lines = usersFile.readlines()
for i, user in enumerate(users):
if userEntry == users[index][0]:
foundName = 1
passwordEntry = raw_input("Enter your password: ")
if passwordEntry == users[index][1]:
print "Username and passwords are correct"
break
else:
print "incorrect"
userEntry = ""
if foundName == 0:
print "Username not recognised"
userEntry = ""
My problem was that I was never receiving an "Enter your password" despite knowing that the username I was entering was in fact in the text file in that list. I kept getting "Username not found back" even though I knew it was there. There was mention of not having referred back to lines but again, not sure how I would go about doing that. If someone could help me out by changing up my code and explaining that would be fantastic. I have been referred to documents trying to explain it and have done by own research on the topic but none of it makes sense to me. A written example in this context would help me out a lot.

So, if I understood correctly by looking at the other two questions (1 and 2) you made related to this, your problem has two parts:
One is generating a file with a list of user/passwords and the second is using that file to do a "login" system.
The problem with writing to files is that you can regard a file as just text... It doesn't really retain the concept of a Python list so you need to figure out a way to convert your fancy users list of lists to text and then back to a list of lists so you can actually use it.
There are many pre-made serializing formats. Here are a few: JSON, CSV, YAML, or the one another user recommended in another question, Pickle
Since in another post you mentioned that you're using this for learning purposes, let's try to keep it as simple as possible ok?
Let's split your exercise in two python files: One to just generate the passwords file and the other that tries to read and verify the username/password that the user entered.
Script 1: Generate the password file.
So... You have a list of username/password pairs, and you have to transform that to text so you can store it in a file. Let's just go through each entry in the list and write it to a file. How about using a bit of inspiration from Linux and use the semicolon character (;) to mark the separation between username and password on each line of the file? Like this:
sample_users = [
["user1", "password1"],
["user2", "password2"],
["user3", "password3"]
]
users_file = open("./users.txt", "w")
for sample_user in sample_users:
username = sample_user[0]
password = sample_user[1]
users_file.write(username + ';' + password + '\n')
users_file.close()
Put that in a .py file and run it. It should generate a file called users.txt right on the same directory where the script is located. I suggest you take a look to the file (any text editor will do). You'll see it looks like this:
user1;password1
user2;password2
user3;password3
By the way, it's a much better practice taking advantage of the "autoclosing" features provided by Python's context managers. You could write that script as:
with open("./users.txt", "w") as users_file:
for sample_user in sample_users:
username = sample_user[0]
password = sample_user[1]
users_file.write(username + ';' + password + '\n')
See? No call to .close() needed. If something happens while running the code, you will be assured that your file is closed after leaving the with block (when the interpreter reaches the end of the with block, a call to the File's special function __exit__ will be automatically run, and the file will be closed)
Script 2: Use the passwords file
Ok... So we have a file with username;password\n on each line. Let's use it.
For this part, you're gonna need to understand what the split (to separate username and password using the semicolon) and rstrip (to remove the newline symbol \n at the end) methods of the str objects do.
We're gonna need to "rebuild" two variables (username and password) from a line of text that has the shape username;password\n. Then see if the username is found in the file, and if so, prompt the user for the password (and verify it's correct):
def loginFunction():
userEntry = ""
foundName = False
while userEntry == "":
userEntry = raw_input("Enter your username: ")
usersFile = open("users.txt", "r")
for line in usersFile:
print("This is the line I read:%s", line,)
# Read line by line instead of loading the whole file into memory
# In this case, it won't matter, but it's a good practice to avoid
# running out of memory if you have reaaaally large files
line_without_newline = line.rstrip('\n') # Remove ending \n
user_record = line_without_newline.split(';') # Separate into username and password (make the line a list again)
userName = user_record[0]
password = user_record[1]
# Might as well do userName, password = line_without_newline.split(';')
if userName == userEntry:
foundName = True
print("User found. Verifying password.")
passwordEntry = raw_input("Enter your password: ")
if passwordEntry == password:
print "Username and passwords are correct"
break
else:
print "incorrect"
userEntry = ""
if not foundName:
print("Username not recognised")
userEntry = ""
if __name__ == "__main__":
loginFunction()
I believe this should do what you want? Put a comment in the answer if you have other questions.
And have fun coding!
PS: So... How about pickle?
Pickle is a module that serializes Python objects into files in a "safer" and more automated way. If you wanted to use it, here's how (one way, at least):
Generating the passwords file:
import pickle
sample_users = [
["user1", "password1"],
["user2", "password2"],
["user3", "password3"]
]
with open('./users.txt', 'w') as f:
pickler = pickle.Pickler(f)
for sample_user in sample_users:
pickler.dump(sample_user)
As before, at this point I would recommend you take a look to how the file users.txt looks like with a regular text editor. You'll see it's pretty different to the file before (the one with the username and password separated by semi colons). It's something like this:
(lp0
S'user1'
p1
aS'password1'
p2
a.(lp3
S'user2'
p4
aS'password2'
p5
a.(lp6
S'user3'
p7
aS'password3'
p8
a.%
Use the file:
import pickle
def loginFunction():
userEntry = ""
while userEntry == "":
userEntry = raw_input("Enter your username: ")
usersFile = open("users.txt", "r")
unpickler = pickle.Unpickler(usersFile)
while True:
try:
user_record = unpickler.load()
userName = user_record[0]
password = user_record[1]
if userName == userEntry:
print("User found. Verifying password.")
passwordEntry = raw_input("Enter your password: ")
if passwordEntry == password:
print "Username and passwords are correct"
else:
print "incorrect"
userEntry = ""
# Watch out for the indentation here!!
break # Break anyway if the username has been found
except EOFError:
# Oh oh... the call to `unpickler.load` broke
# because we reached the end of the file and
# there's nothing else to load...
print("Username not recognised")
userEntry = ""
break
if __name__ == "__main__":
loginFunction()
If you realize, when you do user_record = unpickler.load(), you already get a 2 items Python list in the user_record variable. There's no need for you to transform from text onto list: the unpickler has already done that for you. This is possible thanks to of all that "extra" information that was stored by picker.dump into the file, which allows the unpickler to "know" that the object that needs to be returned is a list.

This is the way you create a login system with pickle however i don't recommend this as there is lot of security issue.I would prefer connecting python to SQL server and storing password in the database.
import pickle
def register(username,password):
user_details = dict()
with open("users.txt",'rb') as f:
user_details = pickle.load(f)
if username in user_details:
print "User already exsits"
else:
user_details[username] = password
print "User added successfully"
with open("users.txt",'wb+') as f:
pickle.dump(user_details,f)
def login(username,password):
user_details = dict()
with open("users.txt",'rb') as f:
user_details = pickle.load(f)
if username in user_details:
if user_details[username] == password:
print "Correct Login successful"
else:
print "Incorrect Details"
def init():
user_details = dict()
with open("users.txt",'wb+') as f:
pickle.dump(user_details,f)
init()
register("s","s")
login("s","s")
To initialise call the init() function.

Related

Using binary search and recursion to search a text file

I want to use recursion and binary search to search a text file for a username and password. Each account (username and password) are saved on one line, with a space separating the two.
This is what I currently have (does work), just want to use more techniques:
def validation(username1, password1):
file = open("Accounts.txt", "r")
for line in file:
line = line.split("\n")
line = line[0].split(" ")
if username1 == line[0] and password1 == line[1]:
main_menu() #main_menu() will allow the user to enter the game
else:
valid = Label(root, text="Account not found try again or sign up")
valid.place(x=215, y=130)
login() #will recall the login window and ask them to renter details
file.close()
I have the following code which I want to use:
def validation(username1, password1):
file = open("Accounts.txt", "r")
userame1 and passwrod1 are the details that the user have entered. I now want to check that an account has already been created using binary search and recursion.
Amy ideas on how to do this? I'm still learning how to code.
The simplest way would be to read all lines and sort them, so that binary search can be applied.
def validation(username1, password1):
file = open("Accounts.txt", "r")
lines = [i.strip().split() for i in file.readlines()]
# lines is a list of [username, password] sublists
lines.sort()
if binary_search(lines, [username1, password1]):
login()
else:
print(“User Not Found”)
you can try to see if a specific word is in the text file:
def validation(username1, password1):
file = open("Accounts.txt", "r")
content = file.read()
if str(username1) and str(password1) in content:
return True
else:
return False
And then call main_menu() or login() depending of the result of validation()

Error whilst trying to delete string from a 'txt' file - Contacts list program

I'm creating a Contact list/book program which can create new contacts for you. Save them in a 'txt' file. List all contacts, and delete existing contacts. Well sort of. In my delete function there is an error which happens and I can't quite tell why?. There isn't a error prompted on the shell when running. It's meant to ask the user which contact they want to delete, find what the user said in the 'txt' file. Then delete it. It can find it easily, however it just doesn't delete the string at all.
I have tried other methods including if/else statements, other online code (copied) - nothing works.
import os, time, random, sys, pyautogui
#function for creating a new contact.
def new_contact():
name = str(input("Clients name?\n:"))
name = name + " -"
info = str(input("Info about the client?\n:"))
#starts formatting clients name and info for injection into file.
total = "\n\n"
total = total + name
total = total + " "
total = total + info
total = total + "\n"
#Injects info into file.
with open("DATA.txt", "a") as file:
file.write(str(total))
file.close
main()
#function for listing ALL contacts made.
def list():
file = open("DATA.txt", "r")
read = file.read()
file.close
#detects whether there are any contacts at all. If there are none the only str in the file is "Clients:"
if read == "Clients:":
op = str(input("You havn't made any contacts yet..\nDo you wish to make one?\n:"))
if op == "y":
new_contact()
else:
main()
else:
print (read)
os.system('pause')
main()
#Function for deleting contact
def delete_contact():
file = open("DATA.txt", "r")
read = file.read()
file.close
#detects whether there are any contacts at all. If there are none the only str in the file is "Clients:"
if read == "Clients:":
op = str(input("You havn't made any contacts yet..\nDo you wish to make one?\n:"))
if op == "y":
new_contact()
else:
main()
else:
#tries to delete whatever was inputted by the user.
file = open("DATA.txt", "r")
read = file.read()
file.close
print (read, "\n")
op = input("copy the Clinets name and information you wish to delete\n:")
with open("DATA.txt") as f:
reptext=f.read().replace((op), '')
with open("FileName", "w") as f:
f.write(reptext)
main()
#Main Menu Basically.
def main():
list_contacts = str(input("List contacts? - L\n\n\nDo you want to make a new contact - N\n\n\nDo you want to delete a contact? - D\n:"))
if list_contacts in ("L", "l"):
list()
elif list_contacts in ("N", "n"):
new_contact()
elif list_contacts in ("D", "d"):
delete_contact()
else:
main()
main()
It is expected to delete everything the user inputs from the txt file. No errors show up on shell/console, it's as if the program thinks it's done it, but it hasn't. The content in the txt file contains:
Clients:
Erich - Developer
Bob - Test subject
In your delete function, instead of opening DATA.txt, you open "FileName"
When using “with”, a file handle doesn't need to be closed. Also, file.close() is a function, you didnt call the function, just its address.
In addition, in the delete function, you opened “fileName” instead of “DATA.txt”

How to check if two strings are on the same line when reading from a .txt file

I am trying to make a notepad program, where you need to sign in first to read the notes you made previously.
During registration, the usernames are saved onto "Usernames.txt", the passwords on "Passwords.txt".To validate whether the username matches up with the password, I want to check whether the line that a certain username is on is the same as the line where is the password that goes with the username is located.
Any help would be greatly appreciated.
You can open both files and iterate them simultaneously:
with open('username.txt') as users, open('password.txt') as passwds:
for user, passwd in zip(users, passwds):
# Check username/password here
However, this isn't a very good storage layout; if you experience any errors reading or writing the files your authentication database can become corrupt and one user could end up with another user's password.
You'd be much better to store both properties in a single file. JSON or even CSV would be acceptable, but using the built in sqlite3 module would be best.
I will not comment on your code, but I'll focus on this aspect only:
I want to check whether the line that a certain username is on is the
same as the line where is the password that goes with the username is
located.
# Open the users file, read its content.
u = open("Usernames.txt","a+")
all_users = u.readlines()
# Compare each line with the username you are looking for.
user_to_find = "Sam"
line_where_user_was_found = None
for n,user in enumerate(all_users):
if user == user_to_find:
line_where_user_was_found = n
break
# Open the passwords file, read its content.
p = open("Passwords.txt","a+")
all_passwords = p.readlines()
# Compare each lines with the password you are looking for.
password_to_find = "1234"
line_where_password_was_found = None
for m,password in enumerate(all_passwords):
if password == password_to_find :
line_where_password_was_found = m
break
# Check if the username-password pair matches.
does_it_match = (line_where_user_was_found == line_where_password_was_found)
You can read a file's lines into a list:
with open("Usernames.txt") as f:
usernames = f.readlines()
And you can get the line number of a particular string with index:
ix = usernames.index(username)
And you can of course get the password at that index by reading the password file into another list and looking at passwords[ix].
Check this code:
username_to_check = "john"
password_to_check = "1234"
file_usernames = open('usernames_filepath_here')
file_passwords = open('passwords_filepath_here')
usernames = file_usernames.read().splitlines()
passwords = file_passwords.read().splitlines()
login_succeed = False
for i in range(0, len(usernames)):
if usernames[i] == username_to_check and passwords[i] == password_to_check:
login_succeed = True
print(login_succeed)
This should get you what you want:
# Get login credentials from user and cast from unicode to string
username = str(raw_input("username:"))
password = str(raw_input("password:"))
# Get all valid usernames as a list and remove newlines from end
with open("Usernames.txt") as usernameFile:
usernameList = [line.replace("\n", "") for line in usernameFile.readlines()]
# Get all valid passwords as a list and remove newlines from end
with open("Passwords.txt") as passwordFile:
passwordList = [line.replace("\n", "") for line in passwordFile.readlines()]
# Figure out which lines the user's username and password are on
lineOfUsername = -2
lineOfPassword = -1
try:
lineOfUsername = usernameList.index(username)
lineOfPassword = passwordList.index(password)
# If either is not found, inform the user
except ValueError:
print("Bad username or password")
exit()
# If the lines match, then you got there!
if(lineOfUsername == lineOfPassword):
# Your logic here
print("Valid login")
# Otherwise, you didn't (womp, womp)
else:
print("Bad username or password")
A few caveats:
This is horrible for security. As in, this is not a security solution. If you wonder why, look up the subject on computerphile on YouTube.
If the either the username or password have dups, that is not accounted for here. And really can't be, given the parameters of your question.

How can I save input to a file and then check the input from the file?

I'm trying to create a VERY basic little operating system just for fun, using Python. So far I have this:
rUsername = input("Create a new user: ")
rPassword = input("Create a password for the user: ")
tUsername = input("Username: ")
def username():
if tUsername != rUsername:
print("User not found.")
blank = input("")
exit()
username()
def password():
if tPassword != rPassword:
print("Incorrect password.")
blank = input("")
exit()
tPassword = input("Password: ")
password()
def typer():
typerCMD = input("")
print ("Hello, and welcome to your new operating system. Type 'help' to get started.")
shell = input("--")
if shell == ("help"):
print("Use the 'leave' command to shut down the system. Use the 'type' command to start a text editor.")
shell2 = input ("--")
if shell2 == ("leave"):
print("Shutting down...")
exit()
if shell2 == ("type"):
typer()
But I want the program to run so that it will save the created username to a file so you don't have to create a new username every time you run it. Any tips? (And please don't judge me on my "text editor." That's just there so that there's a purpose to signing in.)
You can create a dictionary of of username and corresponding password, and then save it to json file.
Suppose your dictinoary is of the type
user_dict = {rUsername : rPassword}
Save into the file "user.json" ie. Write operations
import json
with open("users.json", "w") as f:
json.dumps(user_dict,f)
Read Operations
import json
with open("users.json", "r") as f:
user_dict = json.loads(f)
You can write to a file like this
with open('myfile.txt', 'w') as f:
f.write(rUsername)
a simple program that asks the user for their username and checks if it's in a file, if it's not present it writes their name to the file, thereby creating a new user, with this logic you should be on your way
while True:
username = input('please enter your username or exit to quit the program')
if username == 'exit':
break
else:
with open('myfile.txt', 'r') as f:
for line in f:
print(line)
if username == line:
print('you belong here')
break
else:
with open('myfile.txt', 'a') as f:
f.write(username)
print('You dont belong but your name has been saved')
break
Following are function of Create User and check user present in system or not.
We are used Pickle library to store user details in dictionary structure.
Demo Code:
import os
import pickle
user_details_file = "user_details1.txt"
def createNewUser():
"""
Create New USer.
1. Accept USer name and PAssword from the User.
2. Save USer Name and Password to File.
"""
#- Check Login Detail file is present or not.
if os.path.isfile(user_details_file):
#- Load file into dictionary format.
fp = open(user_details_file, "rb")
data = pickle.load(fp)
fp.close()
else:
#- Set empty dictionary when user details file is not found.
data = {}
while 1:
username = raw_input("Enter Username:").strip()
if username in data:
print "User already exist in system. try again"
continue
password = raw_input("Enter password:")
data[username] = password
#- Save New user details in a file.
fp = open(user_details_file, "wb")
pickle.dump(data, fp)
fp.close()
return True
def loginUSer():
"""
Login User.
1. Open User Name and Password file.
2. Accept User name and Password from the User.
3. check User is present or not
"""
#- Check Login Detail file is present or not.
if os.path.isfile(user_details_file):
fp = open(user_details_file, "rb")
data = pickle.load(fp)
fp.close()
else:
#- Load file into dictionary format.
# We can return False from here also but why to tell user that your are first user of this application.
data = {}
username = raw_input("Enter Username:").strip()
password = raw_input("Enter password:").strip()
if username in data and password==data["username"]:
print "You login"
return True
else:
print "No user worong username or password"
return False
if __name__=="__main__":
new_userflag = raw_input("you want to create new user? yes/no").lower()
if new_userflag=="yes":
createNewUser()
loginUSer()
Note:
raw_input() is used in Python 2.x
input in used in Python 3.x
Few links:
File modes to read and write
Pickling and Unpicking

Find password by username

I already have this code. Now I want to change the code, that when someone types in his username, he has to fill in the right password which belongs to the username.
import csv
csvbestand='inlog.csv'
csv = open('inlog.csv', 'r').read().split('\n')[1].split(';')
username= input("Fill in your username: ")
if username == "admin" or username in csv:
print("Username found")
break
else:
print("Username not found")
while True:
import csv
csvbestand='inlog.csv'
csv = open('inlog.csv', 'r').read().split('\n')[2].split(';')
password = input("Fill in your password: ")
if password == "admin" or password in csv:
print("Congratiulations")
break
else:
print("Password not right")
So when the username is ''John'' then I want only the password which belongs to "John" as the right password.
I am supposing your csv will be like this:
user1, hash_pass_u1
user2, hash_pass_u2
user3, hash_pass_u3
...
Just one note before the solution. You are importing the CSV module of Python and you did not use it in your code, such a silly import, just use it.
The solution is simple
import csv
file = 'yourcsv.csv'
found = False
username = input('Write your username: ')
password_csv = None
with open(file, newline='') as csvfile:
reader = csv.reader(csvfile, delimiter=',')
for row in reader:
# row[0] is the first element, the username and row[1] the hash of the password
if row[0] == username:
password_csv = row[1]
found = True
break
if not found:
print('The username is not in our DB.')
while True:
passw = input('Let me your password: ')
hash_passw = your_method_to_get_the_hash(passw)
if hash_passw == password_csv:
print('Congrats, you are logged.')
break
else:
print('Wrong password dude, try again.')
In this way you only read the file once and you will use the CSV Module.
I'm supposing the format of your CSV if it is another format is easy to change the implementation of this solution. If you need some help with the CSV Module the documentation is here, for python2 and python3
Explanation of what you are doing wrong.
When you do the following sentence:
csv = open('inlog.csv', 'r').read().split('\n')[1].split(';')
You are opening the file, read all the file then split the file by \n character, with this you would obtain the following list ['user1;pass1';'user2;pass2','user3;pass3',...] and the last step you do there, is select the second element with [1], the result of this would be the string 'user2;pass2'. But the statement does not finish here, there is another split that would give you the list ['user2','pass2'].
So you are comparing that the username is admin or is in the list ['user2','pass2']. The same happens when you try to compare the password, but this time you select the third element.
with open('Usernames.txt', 'r') as f:
content = f.readlines()
index = [x for x in range(len(content)) if password in content[x].lower()]
index = (str(index)[1:-1])
if index == '':
print("user not found")
else:
index = (int(index))
with open('passwords.txt', 'r') as d:
d = d.readlines()
f = (d[index]).strip()
if password == f:
print("found password")
If I wanted to use separate files(txt) to contain usernames and passwords I would do this. It grabs the line no. the username is on, then in parallel the password

Categories