I am currently making a log in system which stores usernames and passwords in a text file.
This is my code:
import csv
Brugere = open("D:\Filer\Programmering/Profiles.txt","r+",newline="\n")
writer = csv.writer(Brugere, delimiter=",")
print("Welcome to the chat app!")
Brugernavn = "" //means username
Kodeord = "" // means password
def Signup(j,k):
print("Welcome to sign up!\n Please enter your Username")
j = input("")
if j not in Brugere:
print("Hello, " + j + ", please enter a password:")
k = input("")
line1 = [j,k]
writer.writerow(line1)
print("Great! Now you can sign in")
Signin(Brugernavn, Kodeord)
else:
print("Username already taken! try again")
Signup(Brugernavn, Kodeord)
def Signin(U,P):
print("Welcome to sign in!")
print("Do you already have an account?[y/n]")
ans = input("")
if ans == "n":
print("You will now be redirected to sign up")
Signup(Brugernavn, Kodeord)
elif ans == "y":
U = input("Username: ")
if U in Brugere:
P = input("Password: ")
print("WELCOME")
else:
print("Invalid username, try again")
Signin(Brugernavn, Kodeord)
else:
print("Please write 'y' or 'n'")
Signin(Brugernavn, Kodeord)
Signin(Brugernavn, Kodeord)
Brugere.close()
When I run it, the signup function works as it should, but when the signin function is called, it can't find the username and password from the text file. I think it's because they only get appended after the script is done running. However, 'Im not sure.
I've been struggling for a long time with this csv file thing. I want to have it like
this where each line is a list where I can find the username and password
I've heard people calling it "comma seperated values", however I have no idea how to do it.
TL;DR:
I suspect the simplest solution is:
...
if j not in brugere:
...
writer.writerow(line1)
brugere.flush() # Flush pending changes to file.
...
...
However, I've noticed a few things worthy of consideration:
Python help. You can get help on Python things within an interactive Python session:
python
> import csv
> help(csv)
CSV for this sort of usecase isn't a good idea. If it's production grade use a proper DB, if you're just playing around locally to get a feel for Python use a dict() and store as JSON. I.e.:
import json
username = "myuser"
password = "password"
filename = "data.json"
# Reads data. Requires file `data.json` to exist, with content `{}`.
with open(filename, "r") as data_stream:
data = json.load(data_stream)
if username in data:
print(f"User {username} exists.")
else:
data[username] = password # You'd usually hash and salt a password. It's a separate topic.
# Writes data to disk.
with open(filename, "w") as data_stream:
data_stream.write(json.dumps(data, indent=2)) # Makes it look pretty on disk.
Note that open() returns a stream wrapped in class io.TextIOWrapper (see python -c "import io; help(io.TextIOWrapper)"). It's basically an interface to get the data you want, not the data itself. Try open("test.txt").readlines() to actually read data from stream, for example. Note that streams are consumables.
When you call in on the stream Brugere you're calling the __contains__() dunder method on class io.TextIOWrapper which isn't implemented. But Python being Python it returns False (it's not meaningful).
The CSV interfaces are pretty straightforward:
import csv
filename = "test.txt"
f = open(filename, "w")
writer = csv.writer(f)
writer.write(["myuser", "password"])
# Flushes lines to file.
f.flush()
...
f.close()
Creating a CSV is as simple as writing a string with each value separated by a designated character, often a comma as the name implies. You don't really need the csv library for that.
Your Signup method would then look as follows:
def Signup(j,k):
print("Welcome to sign up!\n Please enter your Username")
j = input("")
if j not in Brugere:
print("Hello, " + j + ", please enter a password:")
k = input("")
line1 = [j,k]
# Write a string with a comma between the values
Brugere.write("{}, {}\n".format(j, k))
print("Great! Now you can sign in")
Signin(Brugernavn, Kodeord)
else:
print("Username already taken! try again")
Signup(Brugernavn, Kodeord)
With that being said, using CSVs to store operational data in a an application does not make all that much sense to me. Please see below for a modified version of signup using SQLite, which is much more robust and still simple to use:
import sqlite3
con = sqlite3.connect('brugere.db')
cur = con.cursor()
# Create a user table with bruger and kodeord
# I added an extra field for when the user was created as well
# which defaults to the date and time the user was created
cur.execute("""create table if not exists brugere
(brugernavn text,
kodeord text,
dato_oprettet TIMESTAMP DEFAULT CURRENT_TIMESTAMP)""")
con.close()
def signup():
con = sqlite3.connect('brugere.db')
cur = con.cursor()
with con:
print("Please enter your Username")
bruger = input()
cur.execute("select brugernavn from brugere where brugernavn =?", [bruger])
bruger_eksisterer = cur.fetchone()
if bruger_eksisterer:
print("Username already taken! Try again")
# Signup(Brugernavn, Kodeord)
else:
print("Hello, " + bruger + ", please enter a password:")
kodeord = input()
try:
cur.execute("insert into brugere (brugernavn, kodeord) values (?, ?)", (bruger, kodeord))
print("Great! Now you can sign in")
except sqlite3.Error as Err:
print("Couldn't add user.\nError: {}".format(Err))
# Signin(Brugernavn, Kodeord)
con.close()
signup()
Modifying the signin should be straighforward, but I'll leave that part up to you.
Related
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("|")
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I have this very simple sign up/log in program for learning purpose, and it works. But it feels like I have code that repeats itself. The must obvious is the check functions.
My question is, should I refactor those two so they become one or is it better to keep them seperate?
def signUp():
username = input("Give me a username: ")
if checkUser(username) == True:
print("You are already registrered, please log in with your password.")
else:
password = input("Also give me a password: ")
with open("sign-up.csv", "a", newline="") as file:
writer = csv.writer(
file, delimiter=",", quotechar='"', quoting=csv.QUOTE_MINIMAL
)
writer.writerow([username, password])
print("You are now signed up. Please log in with your credentials.")
def logIn():
username = input("Give me your username: ")
password = input("Also give me your password: ")
if checkPassword(username, password) == True:
print("Welcome, you are now logged in.")
else:
print("Username or password is incorrect please try again.")
def checkUser(username):
with open("sign-up.csv", "r") as file:
reader = csv.reader(file)
myList = dict(reader)
if username in myList:
return True
else:
return False
def checkPassword(username, password):
with open("sign-up.csv", "r") as file:
reader = csv.reader(file)
myList = dict(reader)
if username in myList and password == myList[username]:
return True
else:
return False
def get_user_choice():
print("\n[1] Sign up")
print("[2] Log in")
print("[q] Quit")
return input("What would you like to do? ")
choice = ""
while choice != "q":
choice = get_user_choice()
if choice == "1":
signUp()
elif choice == "2":
logIn()
elif choice == "q":
print("Welcome back some other day")
else:
print("That choice doesn't exists")
Function checkUser is checking if a username is already present in the csv file. This would happen at signup. The function checkPassword is used when the user is signing in. These functions should stay seperate since they do dramaticly different things with different levels of security concerns. They also expect input based on where the user is in the procces of signup/login. Meaning when you write a function that does both like doBoth(username, password) you have to call this function with a null when you wanna use it at the signup fase in the application doBoth(username, null) since password is never known at signup.
The first obvious factorisation is the common part of both functions - the part tha reads the csv file into a dict:
def read_users():
with open("sign-up.csv", "r") as file:
reader = csv.reader(file)
return dict(reader)
Then you can rewrite check_user and check_password with this function:
def check_user(username):
users = read_users()
return username in users
def check_password(username, password):
users = read_users()
# make sure we work correctly even if
# someone passes `None` as password
_notfound = object()
return users.get(username, _notfound) == password
FWIW, those functions would be better named as (resp.) 'user_exists' and 'authenticate'
Also, you may want to factor out the part that's writing to the csv file - not to reduce code duplication, but to better separate the UI / domain / persistance layers.
def add_user(username, password):
with open("sign-up.csv", "a", newline="") as file:
writer = csv.writer(
file, delimiter=",", quotechar='"', quoting=csv.QUOTE_MINIMAL
writer.writerow([username, password])
def sign_up():
username = input("Give me a username: ")
# note how good naming makes code much more explicit
if user_exists(username):
print("You are already registrered, please log in with your password.")
return # no need to go further
password = input("Also give me a password: ")
add_user(username, password)
def log_in():
username = input("Give me your username: ")
password = input("Also give me your password: ")
if authenticate(username, password):
print("Welcome, you are now logged in.")
return
# oops...
print("Username or password is incorrect please try again.")
Next step would be to replace the input() calls by dedicated ask_username() and ask_password() functions that will validate the user's input. First write them as simply as possible, then find out the common part(s) and see if you can factor them out.
Note that I renamed your functions in all_lower - this is the official coding convention, and Python users tend to strongly adhere to the official coding conventions.
Also note that I removed the useless == True tests. In Python, any expression resolves to an object (in the case of a function call, to the object returned by the function), and every object has a boolean value, so if someexpression == True: is redundant at best. FWIW this is also part of pep8 (official coding conventions). And finally, when you find yourself writing something like:
if someexperession:
return True
else:
return False
You can just simplify it to
return someexpression
Try this:
def checkBoth(username, password):
with open("sign-up.csv", "r") as file:
reader = csv.reader(file)
myList = dict(reader)
if username in myList:
u = True
if password == myList[username]:
p = True
else:
p = False
else:
u = False
p = False
return (u,p)
def checkPassword(username, password):
out = [False, False]
with open("sign-up.csv", "r") as file:
reader = csv.reader(file)
myList = dict(reader)
if username in myList:
out[0] = True
if password == myList[username]:
out[1] = True
return out
and then having a check what is true on the out.
Hey I am trying to create a system using text files where a user can sign up and log in. All the data will be stored in plain text in a text file called User_Data.txt. My code works but I would like to know if there is anything I missed or If I could improve it in any way. Sorry for the Bad code Formatting in advance.
def choices():
print("Please choose what you would like to do.")
choice = int(input("For Sigining Up Type 1 and For Signing in Type 2: "))
if choice == 1:
return getdetails()
elif choice == 2:
return checkdetails()
else:
raise TypeError
def getdetails():
print("Please Provide")
name = str(input("Name: "))
password = str(input("Password: "))
f = open("User_Data.txt",'r')
info = f.read()
if name in info:
return "Name Unavailable. Please Try Again"
f.close()
f = open("User_Data.txt",'w')
info = info + " " +name + " " + password
f.write(info)
def checkdetails():
print("Please Provide")
name = str(input("Name: "))
password = str(input("Password: "))
f = open("User_Data.txt",'r')
info = f.read()
info = info.split()
if name in info:
index = info.index(name) + 1
usr_password = info[index]
if usr_password == password:
return "Welcome Back, " + name
else:
return "Password entered is wrong"
else:
return "Name not found. Please Sign Up."
print(choices())
There is a lot of improvements You could do.
First of all, split functionality to smaller function.
PASSWORD_FNAME = "User_Data.txt"
def get_existing_users():
with open("r", PASSWORD_FNAME ) as fp:
for line in fp.readlines():
# This expects each line of a file to be (name, pass) seperated by whitespace
username, password = line.split()
yield username, password
def is_authorized(username, password):
return any((user == (username, password) for user in get_existing_users())
def user_exists(username):
return any((usr_name == username) for usr_name, _ in get_existing_users())
# above is equivalent of:
#
# for usr_name, _ in get_existing_users():
# if usr_name == username:
# return True
# return False
def ask_user_credentials():
print("Please Provide")
name = str(input("Name: "))
password = str(input("Password: "))
return name, password
def checkdetails():
name, password = ask_user_credentials()
if is_authorized(name, password):
return "Welcome Back, " + name
if user_exists(name):
return "Password entered is wrong"
return "Name not found. Please Sign Up."
def getdetails():
name, password = ask_user_credentials()
if not user_exists(name):
return "Name Unavailable. Please Try Again"
# Not sure tho what would You like to do here
It's always good to remember to always close your file if you read it.
So if you do something like:
f = open("r", "file.txt") remember to always call f.close() later.
If you use context manager and do it like:
with open("r", "file.txt") as fp:
print(fp.read())
it will automatically close the file for you at the end.
Firstly, fix the spelling error at int(input("For Sigining Up Type 1") Other than that I would add some kind of purpose, for example storing secret numbers or something.
For example you can extend your script with a simple password recovery system.
I think it could be useful to learn...
You can implement a sort of a simple hashing system in order to avoid saving the password as plain text.
If you want to add a GUI, please consider using Tkinter.
https://docs.python.org/3/library/tkinter.html
Let we know.
Good Luck and Keep Coding with <3
I am having issues with the current program that I am trying to write. I don't understand why it keeps saying this or why.
Also can this code be extended to cover IP logging and making sure multiple users can be logged in on the same IP in theory?
Here is the code:
import hashlib
import time
#cPickle is faster then pickle but not available in all python releases
#thats why i used a try/accept there
try: import cPickle as cp
#load the database if it exist, if not it create one
try:
f =(r"C:\Users\Owner\Desktop\python\database.data")
data = cp.load(f)
except IOError:
data = {}
#A simple function made to make data dumping easy
def easyDump(data_):
f = file(r"C:\Users\Owner\Desktop\python\database.data", "w")
cp.dump(data_, f)
f.close()
#Get's the date (We'll use this as the custom salt)
def getData():
return str(time.strftime("%d-%m-%Y"))
#A function which accepts two parameters, password and date.
#The date is the custom salt. It returns the sha512 hash excetpyion
def salt(password, date):
salted = hasglib.sha512(password + str(data)).hexdigest()
retun str(salted)
menu = """"
1.Login
2.Register
3.Exit
"""
while True:
print menu
choice = int(raw_input("Your choice please: "))
if choice ==1:
username = raw_input("Enter your username please: ")
password = raw.input("Enter your authentication code please: ")
#if the username is found on the database
if data.has_key(username):
#date is equal to our secured stored data
date = date[username][1]
#check of the given password + date is equal to what is stored on the database
#password
if salt(password, date) == date[username][0]:
print"Welcome %s!" % username
else:
print "Incorrect password"
else:
print "user %s not found, please register!" % username
elif choice == 2:
username = raw_input("Please enter yout username: !")
password = raw_input("Please enter your password: !")
#if username exists in the system already then the name is taken
if data.has_key(username):
print "user %s already registered, please put in another % username
else:
#in order words data = {username: hash, date}
data[username] = [salt(password, getData()), get Data()]
easyDump(data)
print "user %s successfully registereed!" %username
elif choice == 3:
print "goodbye!"
break
else:
print "invaid input or commands"
This code:
try: import cPickle as cp
is not followed by an except ... hence the syntax error
Your code contains many indenting, syntax errors and spelling mistakes. The following fixes these to allow it to at least run:
import hashlib
import time
#cPickle is faster then pickle but not available in all Python releases
#That is why I used a try/accept there
try:
import cPickle as cp
except:
import pickle as cp
#load the database if it exist, if not it create one
try:
f = open(r"C:\Users\Owner\Desktop\python\database.data")
data = cp.load(f)
except IOError:
data = {}
#A simple function made to make data dumping easy
def easyDump(data_):
f = file(r"C:\Users\Owner\Desktop\python\database.data", "w")
cp.dump(data_, f)
f.close()
#Get's the date (We'll use this as the custom salt)
def getData():
return str(time.strftime("%d-%m-%Y"))
#A function which accepts two parameters, password and date.
#The date is the custom salt. It returns the sha512 hash exception
def salt(password, date):
salted = hasglib.sha512(password + str(data)).hexdigest()
return str(salted)
menu = """"
1.Login
2.Register
3.Exit
"""
while True:
print menu
choice = int(raw_input("Your choice please: "))
if choice == 1:
username = raw_input("Enter your username please: ")
password = raw.input("Enter your authentication code please: ")
#if the username is found on the database
if data.has_key(username):
#date is equal to our secured stored data
date = date[username][1]
#check of the given password + date is equal to what is stored on the database
#password
if salt(password, date) == date[username][0]:
print"Welcome %s!" % username
else:
print "Incorrect password"
else:
print "user %s not found, please register!" % username
elif choice == 2:
username = raw_input("Please enter yout username: !")
password = raw_input("Please enter your password: !")
#if username exists in the system already then the name is taken
if data.has_key(username):
print "user %s already registered, please put in another" % username
else:
#in order words data = {username: hash, date}
data[username] = [salt(password, getData()), getData()]
easyDump(data)
print "user %s successfully registered!" % username
elif choice == 3:
print "goodbye!"
break
else:
print "invalid input or commands"
Indenting in Python is very important, getting it wrong can completely change the meaning of the code.
I'm using python 2.7.5 and i'm trying to make a simple program that has a username, password, and checks if it exists in a dictionary. If true, it prints welcome + username, and ignores if false.
First: code.
#!/usr/bin/python
import csv
users = {}
with open('C:\\Users\\chef\\Python\\fn.csv', 'wb') as f: # Just use 'w' mode in 3.x
w = csv.DictWriter(f, users.keys())
w.writeheader()
w.writerow(users)
def new_user():
uname = raw_input("Choose a username: ")
while 1:
pwd = raw_input("Choose a password: ")
check = raw_input("Retype password: ")
if pwd == check:
print "Saved."
users[uname] = pwd
break
if uname in users.keys():
pass
def show_users():
for unames in users.keys():
print unames
def login():
uname = raw_input("Username: ")
pwd = raw_input("Password: ")
if uname in users and pwd in users.values():
print "Welcome, " + uname + "! "
def save():
f=open('C:\\Users\\chef\\Python\\fn.csv', "wb")
w = csv.writer(f)
for key, val in users.items():
w.writerow([key, val])
f.close()
def read():
with open('C:\\Users\\chef\\Python\\fn.csv', 'wb') as f: # Just use 'w' mode in 3.x
w = csv.DictWriter(f, users.keys())
w.writeheader()
w.writerow(users)
print "Welcome to Yubin's 'fake' Email server."
while 1:
read()
choice = raw_input("What would you like to do? ")
if choice == "signup":
new_user()
if choice == "login":
login()
if choice == "showusers":
show_users()
if choice == "logout":
print "You have successfully logged out."
if choice == "quit":
x = raw_input("Are you sure? (y/n) ")
if x == "y":
save()
break
else:
pass
else:
print "Please sign up, log in or see who have signed up."
Problems:
When I first "sign up", i can log in perfectly fine. But, after closing the program and running it again, i can't log in. i assume it's because i set the dictionary empty every time i start, but it's supposed to rewrite the contents into the dictionary. i use windows 7 and in the preview, when i rerun the program, the file becomes empty.
After i write either login, signup or showusers, it prints the last line,
"Please sign up, log in or see who have signed up. "
Please i ask for solutions, and thank you in advance.
EDIT: I solved problem #2, but #1 still is there.
The problem is, as hyades stated, that your read-method overwrites the csv-file instead of reading it. The csv-module offers a reader for this purpose. I have changed your read-method like this to make it work:
def read():
with open('C:\\Users\\chef\\Python\\fn.csv', 'r') as f:
usersReader = csv.reader(f)
for row in usersReader:
if row == []:
pass
else:
users[row[0]] = row[1]
f.close();
You can also remove the "with open..."-code block at the begining of the file (after import and users-declaration).
For Problem 1, might be an issue with the mode of the file. Change it to wb+
Opens a file for both writing and reading in binary format. Overwrites
the existing file if the file exists. If the file does not exist,
creates a new file for reading and writing.
Problem 2 will be solved if you use if..elif instead of if
Check this code above. I use only save and read function. I used read function only once, outside while loop (used 'rb' mode istaed 'wb' mode). I used csv.WriteDict and csv.ReadDict classes enter link description here. to read and save data from users dict. I think You can use shelve or json instead csv, propobly these way will by faster and simply ;)
#!/usr/bin/python
import csv
users = {}
'''def write():
with open('/home/marcin/fn.csv', 'wb+') as f: # Just use 'w' mode in 3.x
w = csv.DictWriter(f, users.keys())
w.writeheader()
w.writerow(users)'''
def new_user():
uname = raw_input("Choose a username: ")
while 1:
pwd = raw_input("Choose a password: ")
check = raw_input("Retype password: ")
if pwd == check:
print "Saved."
users[uname] = pwd
break
if uname in users.keys():
pass
def show_users():
for unames in users.keys():
print unames
def login():
uname = raw_input("Username: ")
pwd = raw_input("Password: ")
if uname in users and pwd in users.values():
print "Welcome, " + uname + "! "
def save():
with open('/home/marcin/fn.csv', "wb+") as f:
fieldnames=['user','pwd']
writer = csv.DictWriter(f,fieldnames=fieldnames)
writer.writeheader()
for key, val in users.items():
writer.writerow({'user' : key, 'pwd' : val})
def read():
with open('/home/marcin/fn.csv','rb') as f: # Just use 'w' mode in 3.x
w = csv.DictReader(f)
for row in w:
print row
users[row['user']]=row['pwd']
def main():
print "Welcome to Yubin's 'fake' Email server."
try:
read()
except IOError:
pass
while 1:
choice = raw_input("What would you like to do? ")
if choice == "signup":
new_user()
save()
if choice == "login":
login()
if choice == "showusers":
show_users()
if choice == "logout":
print "You have successfully logged out."
if choice == "quit":
x = raw_input("Are you sure? (y/n) ")
if x == "y":
save()
break
else:
pass
else:
print "Please sign up, log in or see who have signed up."
if __name__ == "__main__":
main()