length of list read from a csv varies, depending on when a read is performed

Question:

I’m trying to write a simple function that reads in a csv and stores its content inside a list and either returns said list formatted or a string containing the information on why the csv is empty.

For clarification, the csv is provided by an API called via curl. If there is new data available, the csv-structure is as follows:

{
entry1;entry2;entry3
entry1;entry2;entry3
}

however, if there is an error or no data is available, the structure is as follows:

{error code / info / warning / whatever}

so to gather the data, i’m first checking if the csv contains at least more than 2 rows, simply by reading the file and check the length returned via f.readlines(). if that is the case, i filter the data through a list comprehension to ignore the "{}" and return the list as a result. If the list length is below 3, that means there is definitely no data available and that theres solely the error code in line 0 – so i return f.readlines()[0].

here’s the code of the function that does the above said:

def belege_to_list() -> Union[list, str, None]:
    try:
        with open(export_path + "Belege.csv", mode='r', encoding="utf-8") as f:
            if 0 < len(f.readlines()) < 3:
                return str(f.readlines()[0])
            if len(f.readlines()) > 2:
                belege_list = [i.replace("n", "").split(";") for i in f.readlines()[1:-1]]
                return belege_list
    except FileNotFoundError as e:
        print("Belegdatei nicht gefunden.")
        with open(main_path + "log.txt", "a+", encoding="utf-8") as log:
            log.write("[" + str(datetime.now()) + "]: " + "Belege nicht gefunden / Datei fehlt - Error: " + str(e) + "n")
        return None

the csv i’m reading is most definitely containing one line – also at the runtime of the code:

{"error":"sessionid expired or loginname,passwort failed"}

the function is executed as follows:

def main():
    export_belege() # creates csv
    belege = belege_to_list()
    ...

however, im always getting an IndexError: list index out of range at return str(f.readlines()[0]. Now heres the part i sincerely do not understand. If i print out len(f.readlines) BEFORE if 0 < len(f.readlines()) < 3:, the result is 1, the code works. If it’s not printed out however, the len(f.readlines) is supposedly 0, giving me an IndexError: list index out of range. Does anyone have an idea why that might be the case?

Asked By: dzart

||

Answers:

You should save the list returned by readlines() then refer to the list for subsequent operations. Something like this:

from datetime import datetime
export_path = 'foo'
main_path = 'bar'
def belege_to_list():
    try:
        with open(export_path + "Belege.csv", encoding="utf-8") as f:
            lines = list(map(str.strip, f))
            if len(lines) < 3:
                return lines[0] if len(lines) > 0 else None
            if lines[0][0] == '{' and lines[-1][0] == '}':
                return [line.split(';') for line in lines[1:-1]]
    except FileNotFoundError as e:
        print("Belegdatei nicht gefunden.")
        with open(main_path + "log.txt", "a+", encoding="utf-8") as log:
            log.write("[" + str(datetime.now()) + "]: " + "Belege nicht gefunden / Datei fehlt - Error: " + str(e) + "n")
Answered By: Stuart
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.