What is wrong with my python code that seaches through a csv? - python

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.

Related

How to print only a the content of a cell in a specific row from a csv file in Python

I'm new to Python so excuse me if my question is kind of dumb.
I send some data into a csv file (I'm making a password manager). So I send this to this file (in this order), the name of the site, the e-mail corresponding and finally the password.
But I would like to print all the names already written in the csv file but here is my problem, for the first row it does print the whole row but for the following rows it works just well.
Here is my code, I hope u can help me with this.
csv_file = csv.reader(open('mycsvfile.csv', 'r'), delimiter=';')
try :
print("Here are all the sites you saved :")
for row in csv_file :
print(row[0])
except :
print("Nothing already saved")
Maybe it can help, but here is how I wrote my data into the csv file:
#I encrypt the email and the password thanks to fernet and an already written key
#I also make sure that the email is valid
file = open('key.key', 'rb')
key = file.read()
file.close()
f = Fernet(key)
website = input("web site name : \n")
restart = True
while restart :
mail = input("Mail:\n")
a = isvalidEmail(mail)
if a == True :
print("e-mail validated")
restart = False
else :
print("Wrong e-mail")
pws = input("password :\n")
psw_bytes = psw.encode()
mail_bytes = mail.encode()
psw_encrypted_in_bytes = f.encrypt(psw_bytes)
mail_encrypted_in_bytes = f.encrypt(mail_bytes)
mail_encrypted_str = mail_encrypted_in_bytes.decode()
psw_encrypted_str = psw_encrypted_in_bytes.decode()
f = open('a.csv', 'a', newline='')
tup1 = (website, mail_encrypted_str, psw_encrypted_str)
writer = csv.writer(f, delimiter = ';')
writer.writerow(tup1)
print("Saved ;)")
f.close()
return
And here is my output (I have already saved data)
Output (First, you see the name of the ws with the email and the psw encrypted then just the name which is what I want
I finally succeed, instead of using a csv.Reader, i used a csv.DictReader and as all the names i'm looking for are on the same column, i juste have to use the title of the columns.
So here is the code :
with open('mycsv.csv', newline='') as csvfile:
data = csv.DictReader(csvfile)
print("Websites")
print("---------------------------------")
for row in data:
print(row['The_title_of_my_column'])
make list from csv.reader()
rows = [row for row in csv_file]
and now you can get element by identifier using rows as list of lists
rows[id1][id2]

A Way To Store Unknown Amount Of Separate Lists As Columns In A csv File (Python)?

So, I am writing a program that takes user input of four variables in my list: [full_name, first_time, second_time, third_time]. I need to be able to take my list or dictionary, (which ever one is easier?) and have multiple stored lists that then transfer into my csv file named "times.csv" .
This program is meant for a coach to record his athletes running times. I know I can use things like .update and .append to add to one list but I do not know enough about csv files, lists, and programming in general to know how to take user input and store said (separate) lists into a csv file, without replacing the first user inputted column/list.
Maybe some kind of for loop in the writer section of my code??
code below:
import csv
file_name = 'times.csv'
true = 'yes'
while true:
user_entry = input("Do you want an entry? 'yes' to continue, ('no' to stop): ")
if user_entry == 'no':
break
else:
full_name = input("Enter a full name: ")
first_time = float(input("Enter first time: "))
second_time = float(input("Enter second time: "))
third_time = float(input("Enter third time: "))
list1 = [full_name, first_time, second_time, third_time]
print(list1)
with open(file_name, 'r') as csv_file:
csv_reader = csv.reader(csv_file)
fields = next(csv_reader)
for row in csv_reader:
list1.append(row)
print(', '.join(field for field in fields))
with open(file_name, 'w') as csv_file:
write_to_file = csv.writer(csv_file)
write_to_file.writerow(list1)
You could try something like:
Step 1: Create file csv file if not already exist
Step 2: Read the csv file to memory
Step 3: Get the user input and append to the data you read from the csv ( can be looped if there are multiple entries to be read)
Step 4: Write back the data (not append but as new file with the same name)
Implementation:
from pathlib import Path
import csv
def read_existing_data(filename):
csv_file = Path(filename)
csv_file.touch(exist_ok=True)
input_data = [row for row in csv.DictReader(open(filename))]
return input_data
def get_user_input():
entry_list = list()
entry = dict()
true = 'yes'
while true:
user_entry = input("Do you want an entry? 'yes' to continue, ('no' to stop): ")
if user_entry == 'no':
break
else:
entry["full_name"] = input("Enter a full name: ")
entry["first_time"] = float(input("Enter first time: "))
entry["second_time"] = float(input("Enter second time: "))
entry["third_time"] = float(input("Enter third time: "))
entry_list.append(entry)
return entry_list
def save_to_file(filename, csv_data):
columns = csv_data[0].keys()
try:
with open(filename, 'w') as csvfile:
writer = csv.DictWriter(csvfile, fieldnames=columns)
writer.writeheader()
for rows in csv_data:
writer.writerow(rows)
except IOError:
print("I/O error")
file_name = "times.csv"
# Read Existing data
data = read_existing_data(file_name)
# Append new data
data.extend(get_user_input())
# Save to file
save_to_file(file_name, data)

CSV rewriter keeps creating new headers

My code is creating the same headers each time, I want it to create one and append the data to a CSV without creating a new header.
What it looks like in the CSV
What I want it to look like
import csv
with open("Details.csv","a+") as Details:
w=csv.writer(Details,delimiter=",")
headers1=["Name","Age","Year Group"]
line=Details.readlines()
if line!=["Name","Age","Year Group"]:
w.writerow(headers1)
print("Welcome User, to my Topics Quiz!\n-------------------------------
--------\nYou can choose from 3 different topics:\n • History\n •
Music\n • Computer Science\n---------------------------------------")
print("Before we start, we need to register an account.")
User=input("Enter your name:\n")
Age=input("Enter your age:\n")
Year=input("Enter your year group:\n")
details=[User,Age,Year]
w.writerow(details)
Details.close()
with open("UserPass.csv","a+") as Userpass:
w=csv.writer(Userpass,delimiter=",")
headers2=["Username","Password"]
if headers2 not in Userpass:
w.writerow(headers2)
NewUser=(User[:3]+Age)
print("Great! Your username is set to: {}".format(NewUser))
Pass=input("Enter a password for your account:\n")
userpass=[NewUser,Pass]
w.writerow(userpass)
Userpass.close()
Any help is greatly appreciated.
You are opening file in appending mode (https://docs.python.org/3/library/functions.html#open), so this line=Details.readlines() will always be empty line and your headers will be written every time (code will always get into if).
It is similar with other file. So I suggest you first check if file exist, and if not create it and add headers, and remove headers part from with:
import csv
import os.path
if not os.path.isfile("Details.csv"):
with open("Details.csv", "a+") as Details:
w = csv.writer(Details, delimiter=",")
headers1 = ["Name", "Age", "Year Group"]
w.writerow(headers1)
Details.close()
if not os.path.isfile("UserPass.csv"):
with open("UserPass.csv", "a+") as Userpass:
w = csv.writer(Userpass, delimiter=",")
headers2 = ["Username", "Password"]
w.writerow(headers2)
Userpass.close()
with open("Details.csv", "a+") as Details:
w = csv.writer(Details, delimiter=",")
print("Welcome User, to my Topics Quiz!\n-------------------------------"
"--------\nYou can choose from 3 different topics:\n • History\n • "
"Music\n • Computer Science\n---------------------------------------")
print("Before we start, we need to register an account.")
User = input("Enter your name:\n")
Age = input("Enter your age:\n")
Year = input("Enter your year group:\n")
details = [User, Age, Year]
w.writerow(details)
Details.close()
with open("UserPass.csv", "a+") as Userpass:
w = csv.writer(Userpass, delimiter=",")
NewUser = (User[:3] + Age)
print("Great! Your username is set to: {}".format(NewUser))
Pass = input("Enter a password for your account:\n")
userpass = [NewUser, Pass]
w.writerow(userpass)
Userpass.close()
There are different problems in your code:
1) Empty line between lines with data in csv file, it happens because of the nonbinary type of opening and can be fixed by adding that arg in open function:
w=csv.writer(Details,delimiter=",",lineterminator='\n')
2) In your case Details.readlines() method was returning [], because of the a+ type of opening, it's supposed to add lines in the end of file, so pointer is in the end already and we need to return it at the beginning by using that code:
line=Details.seek(0)
3) Also, we need only first line, so just use readline() method. And after all, your condition should look that way, because of the return type and the fact that there's \n in the end of every line:
if line!="Name,Age,Year Group\n":
And the full code of that part. Let me know if it works well for you:
w=csv.writer(Details,delimiter=",",lineterminator='\n')
headers1=["Name","Age","Year Group"]
line=Details.seek(0)
line=Details.readlines()[0]
print(line)
if line!="Name,Age,Year Group\n":
w.writerow(headers1)
I don't understand everything your code is trying to accomplish, but the following will add a row to the Details.csv without creating any new headers:
import csv
import os
csv_fileheader = "Name", "Age", "Year Group"
csv_filename = "Details.csv"
print("Welcome User, to my Topics Quiz!\n"
"---------------------------------------\n"
"You can choose from 3 different topics:\n"
" • History\n • Music\n • Computer Science\n"
"---------------------------------------")
print("Before we start, we need to register an account.")
user = input("Enter your name:\n")
age = input("Enter your age:\n")
year = input("Enter your year group:\n")
if not os.path.isfile(csv_filename): # Create file if it doesn't exist.
with open(csv_filename, "w", newline='') as csv_file:
csv.writer(csv_file).writerow(csv_fileheader) # Put header row in it.
with open(csv_filename, "a+", newline='') as details2:
writer = csv.writer(details2, delimiter=",")
writer.writerow((user, age, year))
You should consider following the PEP 8 - Style Guide for Python Code recommendations as it will make your code easier for both you and others to read.

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

searching a csv and printing a line

Trying to create a train booking system.
Having trouble searching my csv and printing that certain line.
The user already has there id number,and the csv is is set out like
This is what I have so far:
You are matching the entire line against the ID. You need to split out the first field and check that:
def buySeat():
id = raw_input("please enter your ID")
for line in open("customers.csv"):
if line.split(',')[0] == id:
print line
else:
print "sorry cant find you"
Try using the built-in CSV module. It will make things easier to manage as your requirements change.
import csv
id = raw_input("please enter your ID")
ID_INDEX = 0
with open('customers.csv', 'rb') as csvfile:
csvReader = csv.reader(csvfile)
for row in csvReader:
# Ignore the column names on the first line.
if row[ID_INDEX] != 'counter':
if row[ID_INDEX] == id:
print ' '.join(row)
else:
print 'sorry cant find you'

Categories