2009-08-14 3 views
8

Sto cercando di analizzare un file CSV utilizzando il modulo csv di Python (in particolare, la classe DictReader). Esiste un modo Python per rilevare campi vuoti o mancanti e generare un errore?Come posso rilevare i campi mancanti in un file CSV in modo Pythonic?

Ecco un esempio di file utilizzando le seguenti intestazioni: NOME, ETICHETTA, VALORE

foo,bar,baz 
yes,no 
x,y,z 

Durante l'analisi, mi piacerebbe la seconda linea di gettare un errore dal momento che manca il campo del valore.

Ecco un frammento di codice che mostra come sto avvicinando questo (tralasciare le stringhe hard-coded ... sono presenti solo per brevità):

import csv 

HEADERS = ["name", "label", "value" ] 
fileH = open('configFile') 
reader = csv.DictReader(fileH, HEADERS) 

for row in reader: 
    if row["name"] is None or row["name"] == "": 
     # raise Error 
    if row["label"] is None or row["label"] == "": 
     # raise Error 
    ... 
fileH.close() 

c'è un modo più pulito di controllo per campi nel file CSV senza avere un gruppo di istruzioni if? Se ho bisogno di aggiungere altri campi, avrò bisogno anche di altri condizionali, che vorrei evitare se possibile.

risposta

14
if any(row[key] in (None, "") for key in row): 
    # raise error 

Edit: Ancora meglio:

if any(val in (None, "") for val in row.itervalues()): 
    # raise error 
+0

Dolce modo Pythonic! –

+0

Questo metodo è praticamente incompatibile con il comportamento di csv.DictReader. Passerà attraverso tutti i tasti della riga, anche se alcuni di essi potrebbero essere scartati da DictReader perché non sono stati esplicitamente menzionati in HEADERS. Maggiori informazioni qui: http://docs.python.org/library/csv.html#csv.DictReader – Triptych

+0

@Triptych: esiste al massimo una chiave aggiuntiva (il valore passato come restkey al costruttore). Non vedo il problema con questo. – balpha

1

Qualcosa di simile?

... 
for row in reader: 
    for column, value in row.items(): 
     if value is None or value == "": 
      # raise Error, using value of column to say which field is missing 

Si può essere in grado di utilizzare 'se non il valore:' come il test al posto del test più esplicito hai dato.

2

Dal None e stringhe vuote sia valutata come False, si dovrebbe prendere in considerazione questo:

for row in reader: 
    for header in HEADERS: 
     if not row[header]: 
      # raise error 

Si noti che, a differenza di altre risposte , avrai comunque la possibilità di generare un errore informativo, specifico per l'intestazione.

+0

Questo sarà portare a falsi positivi se avete numerici 0 valori in ogni colonna e 'quoting' è impostata a' csv.QUOTE_NONNUMERIC'. –

1

Questo codice fornirà, per ogni riga, un elenco di nomi di campi che non sono presenti (o sono vuoti) per quella riga. Potresti quindi fornire un'eccezione più dettagliata, come "Campi mancanti: foo, baz".

def missing(row): 
    return [h for h in HEADERS if not row.get(h)] 

for row in reader: 
    m = missing(row) 
    if missing: 
     # raise exception with list of missing field names 
0

Se si utilizza matplotlib.mlab.csv2rec, già salva il contenuto del file in un array e sollevare un errore se uno dei valori è mancante.

>>> from matplotlib.mlab import csv2rec 
>>> content_array = csv2rec('file.txt') 
IndexError: list index out of range 

Il problema è che non esiste un modo semplice per personalizzare questo comportamento, o per fornire un valore di default nel caso di righe mancanti. Inoltre, il messaggio di errore non è molto esplicativo (potrebbe essere utile pubblicare un bug report qui).

p.s. dato che csv2rec salva il contenuto del file in un record numpy, sarà più semplice ottenere i valori uguali a None.