Can python interpret lists in text files? - python

I am trying to make a password keeper and I have the usernames and passwords of the user accounts in a text file. However, since the script wants to know if the user input for loginUser and loginPass are in the file, that creates the opportunity for the user to log in with mismatched usernames and passwords. Can I create a list (or at least a pair of strings) and check if the input for the login variables are in a specific list?
Here's my code If you want to test it yourself:
def title():
# This is the title screen
print('____This is a password keeper____')
main()
def main():
abc = open("userpassfile.txt", "r+")
userpassfile = abc.read().strip().split()
actCheck = input('Do you already have an account?')
if(actCheck == 'Yes' or actCheck == 'yes'):
loginUser = input('What is your username?')
loginPass = input('What is yout password?')
if(loginUser and loginPass in userpassfile):
dirCheck = input('Account Settings? [y/n]')
if(dirCheck == 'y' or dirCheck == 'Y'):
print('This function is not working yet!')
else:
print('hihi')
else:
print('Incorrect password or username!')
else:
createAct = input('would you like to create one?')
if (createAct == 'Yes' or createAct == 'yes'):
createUser = input('What would you like your username to be?:')
createPass = input('What would you like your password to be?:')
abc.write(createUser + '\n')
abc.write(createPass + '\n')
open(createUser + '.txt', "w")
title()
If you have any questions about my code, please ask! Thanks!

To me, it would make more sense to store the user / pass pairs in a single line. Something like
user:pass
Or
user|pass
The problem with this approach is that you eliminate a character, the one used as the delimiter, from being used in your username or password. To get around that limitation, you can do something similar to how strings protocol works and prepend the line with a number representing the length of the username.
004userpass
014longerusernamepassword
You read the first 3 characters as an integer, and know how many more to read for the user and how many for the password.
Of course you could also store it in several other formats like json, yaml, or csv,
Given that you are storing them in pairs of lines, you should be able to break them up into their groups with code similar to this:
f = """username1
password1
username2
password2""".splitlines()
pairs = [tuple(f[i*2:i*2+2]) for i in range(len(f)/2)]
print(pairs)
This would output:
[('username1', 'password1'), ('username2', 'password2')]
Then you would simply check
if (loginUser, loginPass) in pairs:
...
You could use a more generic approach for breaking your list of usernames / passwords into pairs as well with this function
def groups(inval, size):
for i in range(0, len(inval), size):
yield inval[i:i+size]
And you could then do
pairs = tuple(groups(f, 2))

Related

ValueError: too many values to unpack (expected 2) on a simple Python function

I'm coding this password manager program and keep getting this error message when I use the view function:
File "c:\Users\user\Desktop\password_manager.py", line 7, in view
user, passw = data.split("|")
ValueError: too many values to unpack (expected 2)
This is the program so far:
master_pwd = input("What is the master password?")
def view():
with open("passwords.txt", "r") as f:
for line in f.readlines():
data = line.rstrip()
user, passw = data.split("|")
print("User:", user, "Password:", passw)
def add():
name = input("Account name: ")
pwd = input("Password: ")
with open("passwords.txt", "a") as f:
f.write(name + "|" + pwd + "\n")
while True:
mode = input("Would you like to add a new password or view existing ones (view, add)? Press q to quit. ").lower()
if mode == "q":
break
if mode == "view":
view()
elif mode == "add":
add()
else:
print("Invalid mode.")
continue
I tried using the .split() method to one variable at a time but it also resulted in the error.
I thought the problem could be caused by the comma in user, passw = data.split("|") being deprecated, but I failed to find an alternative.
The .split() function is returning more than 2 values in a list and therefore cannot be unpacked into only 2 variables. Maybe you have a password or username with a | in it which would cause that.
I suggest to simply print(data.split('|')) for a visual of what is happening. It will probably print out a list with more than two values.
Check your password file to be sure there aren't "|" characters in a username or password that are creating additional splits.
If your data is good, you could catch the remaining elements in a list:
user, passw, *other = data.split("|")

How can I create an input that will loop and create a new list each time?

in case it isn't already obvious im new to python so if the answers could explain like im 5 years old that would be hugely appreirecated.
I'm basically trying to prove to myself that I can apply some of the basic that I have learnt into making a mini-contact book app. I don't want the data to save after the application has closed or anything like that. Just input your name, phone number and the city you live in. Once multiple names are inputted you can input a specific name to have their information printed back to you.
This is what I have so far:
Name = input("enter name here: ")
Number = input("enter phone number here: ")
City = input("enter city here: ")
User = list((Name, Number, City))
This, worked fine for the job of giving python the data. I made another input that made python print the information back to me just to make sure python was doing what I wanted it to:
print("Thank you! \nWould you like me to read your details back to you?")
bck = input("Y / N")
if bck == "Y":
print(User)
print("Thank you! Goodbye")
else:
print("Goodbye!")
The output of this, is the list that the user creates through the three inputs. Which is great! I'm happy that I have managed to make it function so far;
But I want the 'Name' input to be what names the 'User' list. This way, if I ask the user to input a name, that name will be used to find the list and print it.
How do I assign the input from Name to ALSO be what the currently named "User" list
You will need to create a variable which can store multiple contacts inside of it. Each contact will be a list (or a tuple. Here I have used a tuple, but it doesn't matter much either way).
For this you could use a list of lists, but a dictionary will be more suitable in this case.
What is a dictionary?
A dictionary is just like a list, except that you can give each of the elements a name. This name is called a "key", and it will most commonly be a string. This is perfect for this use case, as we want to be able to store the name of each contact.
Each value within the dictionary can be whatever you want - in this case, it will be storing a list/tuple containing information about a user.
To create a dictionary, you use curly brackets:
empty_dictionary = {}
dictionary_with_stuff_in_it = {
"key1": "value1",
"key2": "value2"
}
To get an item from a dictionary, you index it with square brackets, putting a key inside the square brackets:
print(dictionary_with_stuff_in_it["key1"]) # Prints "value1"
You can also set an item / add a new item to a dictionary like so:
empty_dictionary["a"] = 1
print(empty_dictionary["a"]) # Prints 1
How to use a dictionary here
At the start of the code, you should create an empty dictionary, then as input is received, you should add to the dictionary.
Here is the code I made, in which I have used a while loop to continue receiving input until the user wants to exit:
contacts = {}
msg = "Would you like to: \n - n: Enter a new contact \n - g: Get details for an existing contact \n - e: Exit \nPlease type n, g, or e: \n"
action = input(msg)
while action != "e":
if action == "n": # Enter a new contact
name = input("Enter name here: ")
number = input("Enter phone number here: ")
city = input("Enter city here: ")
contacts[name] = (number, city)
print("Contact saved! \n")
action = input(msg)
elif action == "g": # Get details for an existing contact
name = input("Enter name here: ")
try:
number, city = contacts[name] # Get that contact's information from the dictionary, and store it into the number and city variables
print("Number:", number)
print("City:", city)
print()
except KeyError: # If the contact does not exist, a KeyError will be raised
print("Could not find a contact with that name. \n")
action = input(msg)
else:
action = input("Oops, you did not enter a valid action. Please type n, g, or e: ")
#can be easier to use with a dictionary
#but its just basic
#main list storing all the contacts
Contact=[]
#takes length of contact list,'int' just change input from string to integer
contact_lenght=int(input('enter lenght for contact'))
print("enter contacts:-")
#using for loop to add contacts
for i in range(0,len(contact_lenght)):
#contact no.
print("contact",i+1)
Name=input('enter name:')
Number=input('enter number:')
City=input("enter city:")
#adding contact to contact list using .append(obj)
Contact.append((Name,Number,City))
#we can directly take input from user using input()
bck=input("Thank you! \nWould you like me to read your details back to you?[y/n]:")
#checking if user wants to read back
if bck=='y':
u=input("enter your name:")
#using for loop to read contacts
for i in range(0,len(Contact)):
#if user name is same as contact name then print contact details
if u==Contact[i][0]:
print("your number is",Contact[i][1])
print("your city is",Contact[i][2])
else:
#if user doesnt want to read back then print thank you
print("Good bye")
For this purpose you should use a dictionary.
The key of every entry should be the string 'User[0]' that corresponds to the person's name.
The contents of every entry should be the list with the information of that user.
I'll give you an example:
# first we need to create an empty dictionary
data = {}
# in your code when you want to store information into
# the dictionary you should do like this
user_name = User[0] # this is a string
data[user_name] = User # the list with the information
If you want to access the information of one person you should do like this:
# user_you_want string with user name you want the information
data[user_you_want]
Also you can remove information with this command:
del data[user_you_want_to_delete]
You can get more information on dictionaries here: https://docs.python.org/3/tutorial/datastructures.html#dictionaries
You should start by defining a class to support name, phone and city. Once you've done that, everything else is easy.
class Data:
def __init__(self, name, city, phone):
self.name = name
self.city = city
self.phone = phone
def __eq__(self, other):
if isinstance(other, str):
return self.name == other
if isinstance(name, type(self)):
return self.name == other.name and self.city == other.city and self.phone == other.phone
return False
def __str__(self):
return f'Name={self.name}, City={self.city}, Phone={self.phone}'
DataList = []
while (name := input('Name (return to finish): ')):
city = input('City: ')
phone = input('Phone: ')
DataList.append(Data(name, city, phone))
while (name := input('Enter name to search (return to finish): ')):
try:
print(DataList[DataList.index(name)])
except ValueError:
print('Not found')

I would like to use a dictionary to store new user names and password

How do I make this code store new usernames and passwords in a dictionary with username as (K) and password as (V)? Or do I need to store them in a list, if so how would i do it? I've already written another piece of code for logging in of returning users that accesses the username and password as (K) and (V) in the dictionary.
while True:
new_user = input("Consider using alphanumeric and special characters \nCreate new user ID: ")
if len(new_user) < 4:
print("User ID must be more than 4 alphanumeric characters".upper())
continue
elif len(new_user) > 10:
print("User ID must be less than 10 alphanumeric characters".upper())
continue
else:
print("Please confirm user ID ")
break
To build further on the code you've provided, here's a small example. You'll first have to create your dictionary of course. I called it users_and_passwords. Keep in mind that storing users and passwords directly in a dictionary is not at all encouraged!
users_and_passwords = dict()
# get-user loop
while True:
new_user = input("Consider using alphanumeric and special characters \nCreate new user ID: ")
if len(new_user) < 4:
print("User ID must be more than 4 alphanumeric characters".upper())
continue
elif len(new_user) > 10:
print("User ID must be less than 10 alphanumeric characters".upper())
continue
else:
print("Please confirm user ID ")
break
# get-password loop
while True:
user_password = input("Create new user password: ")
# do whatever logic here
# let's assume its fine now
break
After you got your user and password variables filled properly, you can add them as a key:value pair to the dictionary like this:
users_and_passwords[new_user] = user_password
You can then iterate over your users and their passwords like so:
for k, v in users_and_passwords.items():
print (f'user: {k}\thas password: {v}')
To show that this works, with user123 as username and pass123 as a password in this example the output will be:
user:user123 has password: pass123
Watch out with storing passwords directly!
As others have pointed out already, simply scrambling your password irreversibly (e.g. by hashing it, you could take a look at this) and using the scrambled pass as a value for your user would make this a bit safer.
You can create a new dictionary with mydict={}and then store keys and their values with mydict["your-key"] = "your-value"
You can find more here, keep in mind that saving textplain passwords is really dangerous, in particular in this way!
In addition, as user8408080 said:
You would normally instantly hash the password and save that hash.
When the user tries to log in with his password, that is also going to
be hashed and the hashes will be compared. That way nobody can steal
your password from a database
users = [{'K':'john','V':'123456'}]
while True:
username = input("Consider using alphanumeric and special characters \nCreate new user ID: ")
if len(username) < 4:
print("User ID must be more than 4 alphanumeric characters".upper())
continue
elif len(username) > 10:
print("User ID must be less than 10 alphanumeric characters".upper())
continue
else:
# getting the password
password = input('Password: ')
# creating a new user with a dict
new_user = {'K':username,'V':password}
# adding the new user to dict
users.append(new_user)
# I added this for testing purposes, delete these 3 lines in real use
if(len(users) > 1):
break
continue
# and uncomment the next line
# break
def login(username, password):
for user in users:
# checking if the given username and password matches a user in the users list
if(user['K'] == username and user['V'] == password):
print('Logged in')
return True
return False
print('\n\n\n')
print(users)
print('\n\n\n')
print('Log in')
username = input('Username: ')
password = input('Password: ')
login(username,password)
I added the users to a list and in login searched trough the list and checked for username and password matches.
Note: In production never save password in plain text, hash them with something like sha256

Python List object attribute 'append' is read-only

as the title says, in python, I'm trying to make it so when someone types in a choice (in this case Choice13) then it deletes the old password from the list passwords and adds the new one instead.
passwords = ['mrjoebblock' , 'mrjoefblock' , 'mrjoegblock', 'mrmjoeadmin' ]
if choice == '3':
password = raw_input('Welcome admin! I\'m going to need your password ')
if password == 'mrjoeadmin':
print('Welcome Mr. Joe!')
Choice11 = raw_input('What would you like to do? Press 1 for changing your admin password, 2 for viewing a class\'s comments, or 3 for changing a class\'s password')
if Choice11 == '1':
print('You have chosen to change your password! ')
Choice12 = raw_input('You will need to put in your current password to access this feature ')
if Choice12 == 'mrmajoeadmin':
Choice13 = raw_input('What would you like to change your password to? ')
passwords.remove('mrjoeadmin')
passwords.append = Choice13
To append something to a list, you need to call the append method:
passwords.append(Choice13)
As you've seen, assigning to the append method results in an exception as you shouldn't be replacing methods on builtin objects -- (If you want to modify a builtin type, the supported way to do that is via subclassing).
or you could modify the same list slot by doing:
passwords[passwords.index('mrjoeadmin')] = Choice13

Python optimization of simple login system

i don't have a problem with my code but i am very new to python and programming in general so i would like some inputs as to what i could do better.
I decided to do a very simple login / register system and i am hoping you have some input so i can improve myself. I don't post here so often and don't know if this is the sort of question usually asked, but i hope you will help me. Thanks in advance.
Here is the code:
username = ['mel1', 'mel2', 'mel3']
password = ['tyr1', 'tyr2', 'tyr3']
def log_sys():
logged_in = False
log_user = raw_input('Please type in your username: ')
log_pass = raw_input('Please type in your password: ')
if log_user in username:
index = username.index(log_user)
if log_pass == password[index]:
logged_in = True
if logged_in:
print 'You are logged in'
else:
print 'Wrong username or password'
log_sys()
def reg_sys(user):
regpass1 = raw_input('Please choose a password: ')
regpass2 = raw_input('Please retype password: ')
if regpass1 == regpass2:
username.append(user)
password.append(regpass1)
log_sys()
else:
print 'Passwords did not match'
reg_sys(user)
def reglog_system():
reglog = raw_input('Do you want to register or login?: ')
if reglog == 'register':
regname = raw_input('Please choose a username: ')
reg_sys(regname)
elif reglog == 'login':
log_sys()
else:
reglog_system()
reglog_system()
This is not a complete answer; I'm not a python expert.
I would strongly suggest using an associative array or dictionary / hash instead of a list / array for storing usernames and passwords. At a minimum, the performance for large lists of users will be better.
I would move the prompt for username when the user is registering into the function for that process; It seems odd that you pass the username into reg_sys() but prompt in log_sys().
Your test for password seems flawed; You only check to see if the first matches the second, without checking to see if either or both is None, an empty list, the empty string, or some other special value.
I hope that helps.
Got some criticism after all!
1) To make clear what your main function is, you should change:
reglog_system()
to
main()
2) Call your script with:
if __name__ == "main":
main()
Makes it more portable. You can then call it directly or import it as a module
3) Use some return functions:
return raw_input("foo")
And handle the return within main(). It makes your code easier on the eyes and may help deciding when/where to deal with the result of a function.
Performance wise, I can't really criticise anything else, at least nothing springs to mind. For future planning, maybe implement hashing? SHA256 seems pretty robust these days.
i found out that if you use example = input() you can use example directly
Example:
name = input("Username: ")
if name == 'Username':
passwd = input("Password: ")
if passwd == 'Password':
print("Login Sucsessful!")
else:
print("Incorrect Username or password.")

Categories