1

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

monkut
  • 42,176
  • 24
  • 124
  • 155
  • "list index out of range" from `row[1]` means that `row` does not have more than one element (it may only have an element at index 0, or it may be empty). Have you checked your file to make sure every row has at least two 'elements' (contains at least one comma)? – Green Cloak Guy Apr 06 '22 at 05:04
  • If the data is large, you can try `for n, row in enumerate(csv_file):` and putting the inside of the loop in `try .. except IndexError: print('problem in line ', n+1)` - which should tell you what line in the data actually has the problem. – Grismar Apr 06 '22 at 05:09

2 Answers2

-1

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}")
-2

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.

Pranav Hosangadi
  • 23,755
  • 7
  • 44
  • 70