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
CodePudding user response:
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 import
s outside the function because this.
CodePudding user response:
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}")