I am trying to make a login system sort of program but whenever there is more than 1 line of data the code resets the entire CVS file. I need someone to help me with why it's happening. It happens when I choose opt == 2 and search for the name entered 2nd onwards...
reading the CSV file:
try:
df = pd.read_csv('accounts.csv')
for i in range(len(df['name'])):
names.append(df['name'][i])
balances.append(df['balance'][i])
dec_pass = bytes(df['password'][i], 'utf-8')
f = Fernet(key)
decrypted = f.decrypt(dec_pass)
decrypted = decrypted.decode()
passwords.append(decrypted)
except:
with open('accounts.csv', 'w') as f:
f.write(',name,balance,password')
names = []
balances = []
passwords = []
def name_ser(name):
found = False
for i in range(len(names)):
if names[i] == name:
found = True
return found, names.index(name)
else:
found = False
return found
def main_menu():
print('Welcome!\nPlease Choose from the following options...')
print('1: Create an account\n2: Login ')
opt = int(input('Enter Your Choice: '))
if opt == 1:
name_search = input('Enter Name... ')
found, _ = name_ser(name_search)
if found == True:
print("Account Already excites!")
else:
acc_creation(name_search)
print('Account created!')
if opt == 2:
name_search = input('Enter your login name: ')
found, indx = name_ser(name_search)
if found == True:
password = input('Enter your password: ')
dec_pass = bytes(passwords[indx], 'utf-8')
f = Fernet(key)
decrypted = f.decrypt(dec_pass)
decrypted = decrypted.decode()
if password == decrypted:
print('Logged in!')
else:
print('Invalid username or password')
before:
after:
the other thing is when I try to create more than 2 accounts it gives an error and also resets the CSV file. it works fine for the first 2 accounts but gives an error on the second one.
def acc_creation(name):
names.append(name)
balances.append(0)
password_enter = input('Create a Password: ')
encry_p = password_enter.encode()
f = Fernet(key)
encry_pass = f.encrypt(encry_p)
encry_pass = encry_pass.decode('ascii')
passwords.append(encry_pass)
new_df = pd.DataFrame(np.column_stack([names, balances, passwords]),
columns=['name', 'balance', 'password'])
new_df.to_csv('accounts.csv', encoding='utf-8', sep=',',
header=True, na_rep=0, index=True)
Error:
Traceback (most recent call last):
File "/Users/darkmbs/VS-Code/FirstPythonProject/accounts.py", line 91, in <module>
main_menu()
File "/Users/darkmbs/VS-Code/FirstPythonProject/accounts.py", line 79, in main_menu
acc_creation(name_search)
File "/Users/darkmbs/VS-Code/FirstPythonProject/accounts.py", line 54, in acc_creation
new_df = pd.DataFrame(np.column_stack([names, balances, passwords]),
File "<__array_function__ internals>", line 5, in column_stack
File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/numpy/lib/shape_base.py", line 656, in column_stack
return _nx.concatenate(arrays, 1)
File "<__array_function__ internals>", line 5, in concatenate
ValueError: all the input array dimensions for the concatenation axis must match exactly, but along dimension 0, the array at index 0 has size 2 and the array at index 2 has size 1
I believe this may possibly be tied to the name_ser method but cannot be totally sure without seeing what it is doing.
What CSV library are you using? CSV? Panda?
Also, you may want to try adding a return value to the name_ser method to return the index and not have to go through the list again to match it to the password.
Good luck!
--- Edit ---
Every time that you are executing it is opening up the file again and re-writing: ,name,balance,password
If you are wanting to execute more than once, you will need to either:
Write a while loop for main where it will continuously call main_menu()
Check to see if the CSV already exists. If it does, open in read and copy everything and paste it into a new writeable CSV. If it doesn't, move to create the new writeable CSV.
There are quite a few issues here we should address before we try to fix your problem:
your code sample is incomplete, the function name_ser as well as your names and passwords lists are missing
passwords must never be stored in plaintext (unless this code is just for yourself to learn stuff). Please read about Key derivation functions
CSV is not a database where you can easily edit entries inplace. The only safe way to handle this is to overwrite the entire CSV file each time you make a change or to use another data structure (which I would strongly recommend)
Related
I'm attempting to read text from a file and decrypt it using the Fernet cryptography library in Python. So i'm running a For loop which prints all of the text, while it does that I attempt to make the loop decrypt.
from cryptography.fernet import Fernet
from inspect import currentframe
key = "kdQGjocgILOLXj6k_mkkOJOxHxXJji7kdRUTtrGZBTo="
f = Fernet(key)
def get_linenumber():
cf = currentframe()
return cf.f_back.f_lineno
def Main():
choice = input("1. Write Raw Data To File For Encryption\n2. Read Data From File For Decryption\n\nEnter Option Here: ")
if choice == "1":
print("Init Main Successfull On Line ", get_linenumber())
File = open(r"D:\Visual Studio Projects\Python Proj\Secure Note Storage Project\File.txt",mode="a")
FileToEncrypt = bytes(input("Input data to encrypt, Note it will be stored as a string, then heavily encrypted with SHA-256.\n"),'utf-8')
print("\nSuccesfully printed File To Encrypt data on line ",get_linenumber,"\nData From FileToEncrypt Var: ",FileToEncrypt)
FileEncrypted = f.encrypt(FileToEncrypt)
print("\n\n\Here is the final product: ",FileEncrypted)
EncryptionDescription = input("What Is The Data Entered. (Explain For Future Reference!!!)\n\nEnter Here: ")
File.write(f"{EncryptionDescription}\n" + str(FileEncrypted))
File.close()
elif choice == "2":
print("\n\nYou Have Chosen Decryption Method!\n")
File = open(r"D:\Visual Studio Projects\Python Proj\Secure Note Storage Project\File.txt",mode="r")
for line in File:
name = line.strip()
num = File.readline()
num = Fernet.decrypt(f,num)
print (num)
else:
print("Sorry, We Do Not Recognise What You Have Entered. Please look at the options and think...")
exit(0)
###Debug Shit
#print(Fernet.generate_key()) # so i can find one key and keep it static:)
# print(File.read())
# print("File Print Successfull On Line ", get_linenumber())
# File.write("\nRawrar")
if __name__ == "__main__":
Main()
I tried printing the data from the file, then when that worked. I attempted to convert the Num Variable to a decrypted version of the encrypted text. When that didn't work I messed with the parameters a bit. But I got no where, not to sure what Im doing.
The first problem in this case seems to be the fact that you correctly convert FileToEncrypt into bytes for encryption, but when you save it you simply cast it as a string using str(). What you want to do instead is use .decode()
Furthemore you'd probably want to add another linebreak when you write the data to the file. Otherwise you will face issues if you append multiple times to the same file
File.write(f"{EncryptionDescription}\n" + FileEncrypted + "\n") You'd also want to make sure that when loading this data that you convert it to bytes again using bytes(str, 'utf-8').
Now that your data is properly saved into the File.txt file, you are now ready to decode the data. However you will still face an error as you do not pass a timestamp in the decrypt function call, as per the documentation. Essentially I found two ways to do this. One would simply be to call the function with a very high number as the ttl paramater like this: print(Fernet.decrypt(f,bytes(num, "utf-8"), 1000000))
The proper way to do this is to use the function extract_timestamp() as per the documentation. I implemented it like this encryptionTimeStamp = Fernet.extract_timestamp(f, bytes(num, 'utf-8')) with success.
Doing this will get you the unix timestamp at the time of encryption. The ttl parameter is the number of seconds since encryption, you'd want to take the "current unix timestamp - unix timestamp at encryption" and pass that as the ttlparameter.
from cryptography.fernet import Fernet
from inspect import currentframe
import time
key = "kdQGjocgILOLXj6k_mkkOJOxHxXJji7kdRUTtrGZBTo="
f = Fernet(key)
def get_linenumber():
cf = currentframe()
return cf.f_back.f_lineno
def Main():
choice = input("1. Write Raw Data To File For Encryption\n2. Read Data From File For Decryption\n\nEnter Option Here: ")
if choice == "1":
print("Init Main Successfull On Line ", get_linenumber())
File = open(r"File.txt",mode="a")
FileToEncrypt = bytes(input("Input data to encrypt, Note it will be stored as a string, then heavily encrypted with SHA-256.\n"),'utf-8')
print("\nSuccesfully printed File To Encrypt data on line ",get_linenumber,"\nData From FileToEncrypt Var: ",FileToEncrypt)
FileEncrypted = f.encrypt(FileToEncrypt)
FileEncrypted = FileEncrypted.decode()
print("\n\n\Here is the final product: ",FileEncrypted)
EncryptionDescription = input("What Is The Data Entered. (Explain For Future Reference!!!)\n\nEnter Here: ")
File.write(f"{EncryptionDescription}\n" + FileEncrypted + "\n")
File.close()
elif choice == "2":
print("\n\nYou Have Chosen Decryption Method!\n")
File = open(r"File.txt",mode="r")
for line in File:
name = line.strip()
num = File.readline()
numBytes = bytes(num, 'utf-8')
encryptionTimeStamp = Fernet.extract_timestamp(f, numBytes)
currentTime = int(time.time())
timeElapsed = currentTime - encryptionTimeStamp
print( Fernet.decrypt(f,numBytes, timeElapsed))
else:
print("Sorry, We Do Not Recognise What You Have Entered. Please look at the options and think...")
exit(0)
###Debug Shit
#print(Fernet.generate_key()) # so i can find one key and keep it static:)
# print(File.read())
# print("File Print Successfull On Line ", get_linenumber())
# File.write("\nRawrar")
if __name__ == "__main__":
Main()
I'm very new to Python and have only been learning it for a week. I am trying to make a "username selection process" but can't work out how to search a CSV (without errors) to make sure that the name hasn't been used before. Below is my code:
def customusername():
cust = input('Please Enter Custom Username: ')
import csv
import sys
csv_file = csv.reader(open('usernamedatabase.csv', "r",
encoding='utf-8'), delimiter=",")
for row in csv_file:
if cust == row[1]:
print("Username Taken, Try a different name")
customusername()
else:
print("Username Selected")
#I will use code here to place the username
into the database but I already know how to do that
The errors recieved:
Traceback (most recent call last):
File "(the file path)", line 16, in <module>
customusername()
File "(the file path)", line 9, in customusername
if cust == row[1]:
IndexError: list index out of range
BTW I am using visual studio code
I have tried using code from many different websites, all returned errors
This is my solution!
import csv
header = ['UserName']
data = [["Mark"], ["Josh"], ["Lillo"]]
with open("userneame.csv",'w',newline='') as user:
writer=csv.writer(user)
writer.writerow(header)
writer.writerows(data)
NickName = input("username: ").title()
with open('userneame.csv', 'r', newline='') as users:
reader = csv.reader(users)
next(reader) #skips the header
usernames = []
for data in reader: #prints [Mark],[Josh] ecc
for names in data:#Printing all the names in the csv file
usernames.append(names) #just saving the names in the csv file, in a list
if NickName in usernames:
print(f"Sorry {NickName} is not available")
else:
print(f"Nice to meet you {NickName}")
You use recursion where you could use a loop. The call stack has a limit and this can cause your code to error out. You should read the file first, and then loop until you get a valid username. Remember that IO is expensive, so reading the file every time an invalid username is selected is going to take a lot longer than reading it once and remembering it.
import csv
import sys
def customusername():
with open('usernamedatabase.csv', "r", encoding='utf-8') as fh:
# One strategy is to load all rows into a list
csv_file = csv.reader(fh, delimiter=",")
csv_rows_list = list(csv_file)
with open('usernamedatabase.csv', "r", encoding='utf-8') as fh:
# Another is to load all rows into a dict,
# indexed by the 1th column which is presumably the username
csv_file = csv.reader(fh, delimiter=",")
csv_rows_dict = {row[1]: row for row in csv_file}
# Then, you can simply check if the input is in your list or dict:
# 1. List:
while True: # Keep asking for a username until you break
cust = input("Enter your custom username: ")
# if any of the 1th element of the items in
# csv_row_list are equal to username, it is taken
if any(row[1] == cust for row in csv_rows_list):
print("That username is taken. Pick another one.")
else: # Username is available, so end the loop
break
print(f"Hello {username}!")
# 2. Dict:
while True:
cust = input("Enter your custom. username: ")
if cust in csv_rows_dict:
print("That username is taken. Pick another one.")
else: # Username is available, so end the loop
break
print(f"Hello {username}!")
The second approach, with the dict is much better because it is much faster to look up a key in a dict than an item in a list.
If you have memory constraints and can't afford to load the entire csv file, you can simply keep the usernames from it as a set, and check for membership in that set the same way you check if the key exists in the dict.
with open('usernamedatabase.csv', "r", encoding='utf-8') as fh:
csv_file = csv.reader(fh, delimiter=",")
# A set comprehension is subtly different from a dict comprehension
csv_rows_set = {row[1] for row in csv_file}
Note the use of the context manager with to handle automatically closing the file. I also moved the imports outside the function because this.
I'm trying to make my life easier on my work, and writing down errors and solutions for that same errors. The program itself works fine when it's about adding new errors, but then I added a function to verify if the error exists in the file and then do something to it (not added yet).
The function doesn't work and I don't know why. I tried to debug it, but still not able to find the error, maybe a conceptual error?
Anyway, here's my entire code.
import sys
import os
err = {}
PATH = 'C:/users/userdefault/desktop/errordb.txt'
#def open_file(): #Not yet used
#file_read = open(PATH, 'r')
#return file_read
def verify_error(error_number, loglist): #Verify if error exists in file
for error in loglist:
if error_number in loglist:
return True
def dict_error(error_number, solution): #Puts input errors in dict
err = {error_number: solution}
return err
def verify_file(): #Verify if file exists. Return True if it does
archive = os.path.isfile(PATH)
return archive
def new_error():
file = open(PATH, 'r') #Opens file in read mode
loglist = file.readlines()
file.close()
found = False
error_number = input("Error number: ")
if verify_error(error_number, loglist) == True:
found = True
# Add new solution, or another solution.
pass
solution = str(input("Solution: "))
file = open(PATH, 'a')
error = dict_error(error_number, solution)
#Writes dict on file
file.write(str(error))
file.write("\n")
file.close()
def main():
verify = verify_file() #Verify if file exists
if verify == True:
new = str.lower(input("New job Y/N: "))
if new == 'n':
sys.exit()
while new == 'y':
new_error()
new = str.lower(input("New job Y/N: "))
else:
sys.exit()
else:
file = open(PATH, "x")
file.close()
main()
main()
To clarify, the program executes fine, it don't return an error code. It just won't execute the way I'm intended, I mean, it supposed to verify if certain error number already exists.
Thanks in advance :)
The issue I believe you're having is the fact that you're not actually creating a dictionary object in the file and modifying it but instead creating additional dictionaries every time an error is added then reading them back as a list of strings by using the .readlines() method.
An easier way of doing it would be to create a dictionary if one doesn't exist and append errors to it. I've made a few modifications to your code which should help.
import sys
import os
import json # Import in json and use is as the format to store out data in
err = {}
PATH = 'C:/users/userdefault/desktop/errordb.txt'
# You can achieve this by using a context manager
#def open_file(): #Not yet used
#file_read = open(PATH, 'r')
#return file_read
def verify_error(error_number, loglist): #Verify if error exists in file
# Notice how we're looping over keys of your dictionary to check if
# an error already exists.
# To access values use loglist[k]
for k in loglist.keys():
if error_number == k:
return True
return False
def dict_error(loglist, error_number, solution): #Puts input errors in dict
# Instead of returning a new dictionary, return the existing one
# with the new error appended to it
loglist[error_number] = solution
return loglist
def verify_file(): #Verify if file exists. Return True if it does
archive = os.path.isfile(PATH)
return archive
def new_error():
# Let's move all the variables to the top, makes it easier to read the function
# Changes made:
# 1. Changed the way we open and read files, now using a context manager (aka with open() as f:
# 2. Added a json parser to store in and read from file in a json format. If data doesn't exist (new file?) create a new dictionary object instead
# 3. Added an exception to signify that an error has been found in the database (this can be removed to add additional logic if you'd like to do more stuff to the error, etc)
# 4. Changed the way we write to file, instead of appending a new line we now override the contents with a new updated dictionary that has been serialized into a json format
found = False
loglist = None
# Open file as read-only using a context manager, now we don't have to worry about closing it manually
with open(PATH, 'r') as f:
# Lets read the file and run it through a json parser to get a python dictionary
try:
loglist = json.loads(f.read())
except json.decoder.JSONDecodeError:
loglist = {}
error_number = input("Error number: ")
if verify_error(error_number, loglist) is True:
found = True
raise Exception('Error exists in the database') # Raise exception if you want to stop loop execution
# Add new solution, or another solution.
solution = str(input("Solution: "))
# This time open in write only and replace the dictionary
with open(PATH, 'w') as f:
loglist = dict_error(loglist, error_number, solution)
# Writes dict on file in json format
f.write(json.dumps(loglist))
def main():
verify = verify_file() #Verify if file exists
if verify == True:
new = str.lower(input("New job Y/N: "))
if new == 'n':
sys.exit()
while new == 'y':
new_error()
new = str.lower(input("New job Y/N: "))
else:
sys.exit()
else:
with open(PATH, "x") as f:
pass
main()
main()
Note that you will have to create a new errordb file for this snippet to work.
Hope this has helped somehow. If you have any further questions hit me up in the comments!
References:
Reading and Writing files in Python
JSON encoder and decoder in Python
I think that there may be a couple of problems with your code, but the first thing that I noticed was that you are saving Error Numbers and Solutions as a dictionary in errorsdb.txt and when you read them back in you are reading them back in as a list of strings:
The line:
loglist = file.readlines()
in new_error returns a list of strings. This means that verify_error will always return False.
So you have a couple of choices:
You could modify verify_error to the following:
def verify_error(error_number, loglist): #Verify if error exists in file
for error in loglist:
if error_number in error:
return True
Although, I think that a better solution would be to load errorsdb.txt as a JSON file and then you'll have a dictionary. That would look something like:
import json
errordb = {}
with open(PATH) as handle:
errordb = json.load(handle)
So here are the full set of changes I would make:
import json
def verify_error(error_number, loglist): #Verify if error exists in file
for error in loglist:
if error_number in error:
return True
def new_error():
errordb = list()
exitsting = list()
with open(PATH) as handle:
existing = json.load(handle)
errordb += existing
error_number = input("Error number: ")
if verify_error(error_number, errordb) == True:
# Add new solution, or another solution.
print("I might do something here.")
else:
solution = str(input("Solution: "))
errordb.append({error_number, solution})
#Writes dict on file
with open(PATH, "w") as handle:
json.dump(errordb, handle)
I am learning Python as a beginner and have a question that I couldn't figure out. I need to write functions to allow users to setup/give a file a name and then enter contents.
The error message I got is: "Str' object is not callable. I don't know how to fix this. Please could you help me out. Many thanks!
The code is as follows:
=========================================
WRITE = "w"
APPEND = "a"
fName = ""
def fileName(): #to define name of the file.
fName = input("Please enter a name for your file: ")
fileName = open(fName, WRITE)
return fileName
#now to define a function for data entry
dataEntry = ""
def enterData():
dataEntry = input("Please enter guest name and age, separated by a coma: ")
dataFile = open(fName, APPEND(dataEntry))
fName.append(dataEntry)
return dataFile
#to determine if it's the end of data entry
moreEntry = input("Anymore guest: Y/N ")
while moreEntry != "N":
enterData() #here to call function to repeat data entry
fName.close()
fileName()
enterData()
print("Your file has been completed!")
fileContents = fName.readline()
print(fileContents)
I ran the code and... I seeing the error as line 14
14 dataFile = open(fName, APPEND(dataEntry))
APPEND appears to be a str. It does not appear to be a function.
fName is not declared in this scope. Your function spacing is off. Maybe you meant to run the all the code in order rather than in parts?
As it is, fName is declared and defined once globally (line 4), declared and defined in function filename() (line 6).
fName is also referred to in the function (line 7) Called unsuccessfully in line 14
dataFile = open(fName, APPEND(dataEntry)) # fName has not been declared in function enterData()
I suspect your code would work if you reordered your lines and not use functions (due to references) Also, please close your files. EG
f = open ("somefile.txt", "a+")
...
f.close() #all in the same block.
Thanks for all the inputs. Much appreciated. I've reworked the code a bit, and to put all data entry into a list first, then try to append the list to the file. It works, to a certain extent (about 80%, perhaps!)
However, I now have another problem. When I tried to open the file to append the list, it says "No such file or directory" next to the code (line31): "myFile = open(fName, APPEND)". But I thought I declared and then let user define the name at the beginning? How should I make it work, please?
Thanks in advance again!
WRITE = "w"
APPEND = "a"
fName = ""
def fileName(): #to define name of the file.
fName = input("Please enter a name for your file: ")
fileName = open(fName, WRITE)
fileName.close()
return fileName
#now to define a function for data entry
dataEntry = ""
dataList = []
def enterData():
dataEntry = input("Please enter guest name and age, separated by a coma: ")
dataList.append(dataEntry)
return
fileName()
enterData()
#to determine if it's the end of data entry
moreEntry = input("Anymore guest: Y/N ")
if moreEntry == "Y":
enterData()
else:
print("Your file has been completed successfully!")
myFile = open(fName, APPEND)
myFile.append(dataList)
myFile.close()
fileContents = fName.readline()
print(fileContents)
I am writing a program to read a text file of zip codes that should print the location of the zip code when the correct number is input. However, I am having trouble writing the error message. I have tried various methods and cannot get the error message to print, here is what I have:
try:
myFile=open("zipcodes.txt") #Tries to open file user entered
except:
print "File can't be opened:", myFile #If input is invalid filename, print error
exit()
zipcode = dict() #List to store individual sentences
line = myFile.readline() #Read each line of entered file
ask = raw_input("Enter a zip code: ")
if ask not in line:
print "Not Found."
else:
for line in myFile:
words = line.split()
if words[2] == ask:
zipcode = words[0:2]
for value in zipcode:
print value,
Some sample ZIP codes:
Abbeville AL 36310
Abernant AL 35440
Acmar AL 35004
Adamsville AL 35005
Addison AL 35540
Adger AL 35006
Akron AL 35441
Alabaster AL 35007
I'm not sure of the significance of enterFile. You should see the error message if you remove enterFile from the exception because it doesn't appear to be defined.
From the beginning:
try:
myFile=open("zipcodes.txt")
except:
print "File can't be opened:", myFile # if open fail then myFile will be undefined.
exit()
zipcode = dict() # you creating dict, but you never add something into it.
line = myFile.readline() # this will read only first line of file, not each
ask = raw_input("Enter a zip code: ")
if ask not in line:
# it will print not found for any zipcode except zipcode in first line
print "Not Found."
else:
# because you already read 1 line of myFile
# "for line in " will go from second line to end of file
for line in myFile: # 1 line already readed. Continue reading from second
words = line.split()
if words[2] == ask: # If you don't have duplicate of first line this will never be True
zipcode = words[0:2]
# So here zipcode is an empty dict. Because even if "ask is in line"
# You never find it because you don't check line
# where the ask is (the first line of file).
for value in zipcode:
# print never executed becouse zipcode is empty
print value,
I believe that you need two phases in this program:
Read zipcodes.txt and build your directory.
Ask the user for a ZIP code; print the corresponding location.
Your current "positive" logic is
else:
for line in myFile:
words = line.split() # Get the next line from zipcodes.txt
if words[2] == ask: # If this ZIP code matches the input,
zipcode = words[0:2] # assign the line's three fields as a list.
# Variable zipcode now contains a single line's data, all three fields.
# You threw away the empty dictionary.
for value in zipcode: # Print all three fields of the one matching line.
print value,
Needed Logic (in my opinion)
# Part 1: read in the ZIP code file
# For each line of the file:
# Split the line into location and ZIP_code
# zipcode[ZIP_code] = location
# Part 2: match a location to the user's given ZIP code
# Input the user's ZIP code, "ask"
# print zipcode[ask]
Does this pseduo-code get you moving toward a solution?