String Index out of range

As an ignorant, I checked more times my code but I can’t find any error in the way I indexed…
So, what’s wrong with this?

def elenco_completo():

    def chiudi_elenco():
        frm_infospiti.destroy()

    frm_infospiti = Frame(root)
    frm_infospiti.pack()

    entry = Entry(frm_infospiti, width=25, borderwidth=4)
    entry.pack(side=TOP)

    tree_colonne = ttk.Treeview(frm_infospiti, columns=("Cognome", "Nome", "Data di nascita",
                                               "Piano/Camera"), selectmode='extended', height=15)

    tree_colonne ['show'] = 'headings'

    tree_colonne.column('#0')
    tree_colonne.heading('#0')

    tree_colonne.column('#1')
    tree_colonne.heading('#1', text="Cognome")

    tree_colonne.column('#2')
    tree_colonne.heading('#2', text="Nome")

    tree_colonne.column('#3')
    tree_colonne.heading('#3', text="Data di nascita")

    tree_colonne.column('#4')
    tree_colonne.heading('#4', text="Piano/Camera")

    tree_colonne.pack()


    puls_chiudi_elenco = Button(frm_infospiti, text="Chiudi", command=chiudi_elenco)
    puls_chiudi_elenco.pack()


    percorso_elenco = filedialog.askopenfilename(filetypes=[("File CSV", "*.csv")])
    if not percorso_elenco:
        return

    with open(percorso_elenco, 'r') as elenco:
        lettore_elenco = pd.read_csv(elenco)
        for row in lettore_elenco:
            cognome = row[0]
            nome = row[1]
            nascita = row[2]
            piano_camera = row[3]

            tree_colonne.insert("", 0, values=(cognome, nome, nascita,
                                            piano_camera)

    if __name__=='__main__':
        root.mainloop()

It raises this…

Avvio: python3 /path/to/main.py
Exception in Tkinter callback
Traceback (most recent call last):
  File "/usr/lib/python3.10/tkinter/__init__.py", line 1921, in __call__
    return self.func(*args)
  File "/path/to/main.py", line 113, in elenco_completo
    piano_camera = row[3]
IndexError: string index out of range
*** Uscito normalmente ***

Thanks in advance.

What I do, when faced with this kind of issue, is to introduce a so-called ‘print debug’: at the beginning of your for row in lettore_elenco: loop, have a code line print (row), then you’ll be able to see if there is a 4th element to assign to piano_camera

I tried and it prints correctly.
I have omitted that in the example I posted, rows are more than four (I deleted some of them to get it shorter) and everything must be printed in a tkinter GUI using a Treeview table. Could it be relevant?

Hummm, but that flies in the face of the IndexError: The only way (that I can think of) that Python would throw that error, is if there is no row[3]. Did you check that for each loop? It could be fine for a loop or two, then on x count of the loop, it fails.

You could introduce a check branch, so that you only assign a value to piano_camera if there is a value to assign, but that will simply mask the issue, which may (or may not) cause an issue down stream.

I don’t think that the issue is with the GUI part, but I could be wrong about that.

To add: if you do introduce a check branch, I’d make sure that you assign some default value to piano_camera, so that it is clear, in the data, that row[3] failed.

That’s why copying/pasting I modified the message to hide some infos. It would be only an example. The error raises in face of row[7] in the real code.

What I noticed (but I’m not sure about that) is that sometimes it works, sometimes not.
As a newbie, I think it would be something other in my code that would be ‘akward’ for the rest of the program. But it is only a reading function, so, what could be so ‘akward’ reading a document?
Previously I was using the built-in csv module but, follow some suggestion of another user on this forum, I started using pandas because the built-in csv module don’t permit to write in a specific cell.

So far as I can see, your file handler is only being used to read the csv data, so (if this was my code) I’d use the csv.reader for the task, just to keep things as simple as possible: csv files don’t have ‘cells’, per se.

Yes, you’re right. In fact, this is the case. I was talking about pandas only to justify the use of it instead the csv module, using it also for write infos in csv document using other functions in the program, but it is off topic.
The problem here descripted is about the only reading function and the relative index error.

Obviously I’m not an expert, but both the csv module than pandas use column indexation and rows, so yes, those two parameter make a “cell” and it’s possible handle datas also with softwares like LibreOffice Calc…

Sorry, but I need to come back on this topic…

this is the case…

Exception in Tkinter callback
Traceback (most recent call last):
  File "/usr/lib/python3.10/tkinter/__init__.py", line 1921, in __call__
    return self.func(*args)
  File "path/to/main.py", line 125, in elenco_completo
    letto = row[4]
IndexError: list index out of range

and here is my code…

def elenco_completo():

    def chiudi_elenco():
        frm_infospiti.destroy()

    def elimina():
        with open('/path/to/main.py', 'a',
                  encoding='UTF-8') as elenco_aggiornato:

            selezione = tree_colonne.selection()[0]
            values = tuple(tree_colonne.item(selezione)['values'])
            tree_colonne.item(selezione)['values']
            tree_colonne.delete(selezione)

    frm_infospiti = Frame(root)
    frm_infospiti.pack()

    entry = Entry(frm_infospiti, width=25, borderwidth=4)
    entry.pack(side='top')

    tree_colonne = ttk.Treeview(frm_infospiti, columns=("Cognome", "Nome", "Data di nascita",
                                               "Piano/Camera", "Letto", "Malattie/Patologie/Disfunzioni",
                                               "Allergie", "Protesi", "Alimentazione",
                                               "Presidi", "Ausilii", "Riposo"), selectmode='extended', height=15)

    tree_colonne ['show'] = 'headings'

    tree_colonne.column('#0')
    tree_colonne.heading('#0')

    tree_colonne.column('#1')
    tree_colonne.heading('#1', text="Cognome")

    tree_colonne.column('#2')
    tree_colonne.heading('#2', text="Nome")

    tree_colonne.column('#3')
    tree_colonne.heading('#3', text="Data di nascita")

    tree_colonne.column('#4')
    tree_colonne.heading('#4', text="Piano/Camera")

    tree_colonne.column('#5')
    tree_colonne.heading('#5', text="Letto")

    tree_colonne.column('#6')
    tree_colonne.heading('#6', text="Malattie/Patologie/Disfunzioni")

    tree_colonne.column('#7')
    tree_colonne.heading('#7', text="Allergie")

    tree_colonne.column('#8')
    tree_colonne.heading('#8', text="Protesi")

    tree_colonne.column('#9')
    tree_colonne.heading('#9', text="Alimentazione")

    tree_colonne.column('#10')
    tree_colonne.heading('#10', text="Presidi")

    tree_colonne.column('#11')
    tree_colonne.heading('#11', text="Ausilii")

    tree_colonne.column('#12')
    tree_colonne.heading('#12', text="Riposo")

    tree_colonne.pack()


    puls_canc = Button(frm_infospiti, text="Elimina... da elenco", command=elimina)
    puls_canc.pack()

    puls_chiudi_elenco = Button(frm_infospiti, text="Chiudi", command=chiudi_elenco)
    puls_chiudi_elenco.pack()


    percorso_elenco = filedialog.askopenfilename(filetypes=[("File CSV", "*.csv")])
    if not percorso_elenco:
        return

    with open(percorso_elenco, 'r') as elenco:
        lettore_elenco = csv.reader(elenco)
        for row in lettore_elenco:
            cognome = row[0]
            nome = row[1]
            nascita = row[2]
            piano_camera = row[3]
            letto = row[4]
            mal_pat_dis = row[5]
            allergie = row[6]
            protesi = row[7]
            alimentazione = row[8]
            presidi = row[9]
            ausilii = row[10]
            riposo = row[11]

            tree_colonne.insert("", 0, values=(cognome, nome, nascita,
                                            piano_camera, letto, mal_pat_dis,
                                            allergie, protesi, alimentazione,
                                            presidi, ausilii, riposo))

    if __name__=='__main__':
        root.mainloop()

Where is my mistake?

That means that row has only four items, numbered 0, 1, 2, 3. You are trying to get the fifth item, row[4], but it doesn’t exist.

I know that it is sometimes confusing that items are numbered starting with 0. Sorry.

This probably means that one of the rows in your CSV file only has four columns, and you are expecting 12.

The file is correct. I checked it hundreds of times. Reading on the net, I checked for a better comprehension of the two terms “row” and “column”…
What I’m trying to do is to read the file not in horizontal… what I want is read the columns in a vertical sense. What I call with a definition using “row[n]”, would be the vertical reading of the document (if you open LibreCalc or Excel, it would be “column A”, “column B”, “column C”, etc, etc, etc), not from the ID of the line. The strange thing is that once it was readable, but after some correction on other functions (those last use other files) it won’t work anymore. Coulb be it a corelation with something else in my code?

I checked better my csv file and (obviously) you’re right.
Beetween a lot of datas I found a line with only 4 item.
For sure, after hundreds of test, I digited something on my keyboard accidentally.
I know, it is a stupid error but I guess having a silly info like this in a forum help ignorant like me to understand how this stuff works.
Anyway, big thanks!