Perché l'oggetto csv DictReader Dictionary funziona solo mentre il file è ancora aperto?

Aug 23 2020

Sto imparando python e sto giocando con dizionari e file .csv e il modulo csv. Sembra che la csv.DictReader()funzione possa aiutare a trasformare i file .csv in oggetti dizionario, ma c'è un po 'di stranezza con gli oggetti Reader di cui sono confuso.

Ho letto un po 'nella documentazione (e poi ho cercato di trovare le risposte guardando la csv.Reader()funzione), ma sono ancora un po' insicuro.

Perché questo codice viene eseguito come previsto:

with open("cool_csv.csv") as cool_csv_file:
  cool_csv_text = cool_csv_file.read()

print(cool_csv_text)

e tuttavia il codice seguente restituisce un file ValueError: I/O operation on closed file.

with open("cool_csv.csv") as cool_csv_file:
  cool_csv_dict = csv.DictReader(cool_csv_file)

for row in cool_csv_dict:
  print(row["Cool Fact"])

Dato che abbiamo salvato l' DictReaderoggetto in una variabile python, non dovremmo essere in grado di chiamare la variabile dopo aver chiuso il file, come se fossi stato assegnato cool cool_csv.read()?

So che il modo corretto per codificare questo sarebbe:

with open("cool_csv.csv") as cool_csv_file:
  cool_csv_dict = csv.DictReader(cool_csv_file)
  for row in cool_csv_dict:
    print(row["Cool Fact"])

Ma perché la for row in cool_csv_dict:sezione deve essere annidata nella open()sezione?

La mia unica ipotesi sarebbe che, poiché l' csv.DictReader()oggetto non è proprio un vero dizionario (o qualcosa del genere), ci sono degli imbrogli perché deve ancora puntare da qualche parte (perché forse questa è la parte "lettore"?).

Qualcuno può chiarire?

Risposte

2 Barmar Aug 23 2020 at 01:06

csv.DictReadernon legge l'intero file in memoria quando crei l' cool_csv_dictoggetto. Ogni volta che lo chiami per ottenere il record successivo dal CSV, legge la riga successiva da cool_csv_file. Pertanto, deve essere tenuto aperto in modo che possa leggere da esso se necessario.

L'argomento per csv.DictReaderpuò essere qualsiasi iteratore che restituisce righe. Quindi, se non vuoi mantenere il file aperto, puoi chiamare readlines()per inserire tutte le righe in un elenco, quindi passarlo acsv.DictReader

with open("cool_csv.csv") as cool_csv_file:
    cool_csv_lines = cool_csv_file.readlines()
cool_csv_dict = csv.DictReader(cool_csv_lines)
for row in cool_csv_dict:
    print(row("Cool Fact")