2009-08-14 16 views
8

Estoy tratando de analizar un archivo CSV usando el módulo csv de Python (específicamente, la clase DictReader). ¿Hay alguna forma Pythonic para detectar campos vacíos o faltantes y arrojar un error?¿Cómo puedo detectar los campos faltantes en un archivo CSV de forma pitonica?

Aquí hay un ejemplo de archivo con los siguientes encabezados: NOMBRE, ETIQUETA, VALOR

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

Al analizar, me gustaría que la segunda línea de lanzar un error, ya que le falta el campo VALUE.

He aquí un fragmento de código que muestra cómo me acerco a este (caso omiso de las cadenas no modificables ... son sólo está presente por razones de brevedad):

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() 

¿Existe una forma más limpia de la comprobación de campos en el archivo CSV sin tener un montón de declaraciones if? Si necesito agregar más campos, también necesitaré más condicionales, lo que me gustaría evitar si es posible.

Respuesta

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

Editar: Aún mejor:

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

Sweet Pythonic way! –

+0

Este método es bastante incompatible con el comportamiento de csv.DictReader. Pasará por todas las teclas de la fila, aunque el DictReader podría descartar algunas de ellas, ya que no se mencionaron explícitamente en HEADERS. Más aquí: http://docs.python.org/library/csv.html#csv.DictReader – Triptych

+0

@Triptych: Hay como máximo una de esas claves adicionales (el valor pasado como clave de reposo para el constructor). No veo el problema con eso. – balpha

1

¿Algo como esto?

... 
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 

Puede utilizar 'if not value:' como su prueba en lugar de la prueba más explícita que dio.

2

Desde None y cadenas vacías ambas evaluar a False, se debe considerar lo siguiente:

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

Tenga en cuenta que, a diferencia de algunas otras respuestas , aún tendrá la opción de generar un error informativo, específico del encabezado.

+0

Esto dará lugar a falsos positivos si tiene valores 0 numéricos en cualquier columna, y 'citando' está establecido en 'csv.QUOTE_NONNUMERIC'. –

1

Este código proporcionará, para cada fila, una lista de nombres de campo que no están presentes (o están vacíos) para esa fila. A continuación, puede proporcionar una excepción más detallada, como "Campos faltantes: 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

Si utiliza matplotlib.mlab.csv2rec, ya se guarda el contenido del archivo en una matriz y generará un error si uno de los valores de falta.

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

El problema es que no hay una forma sencilla de personalizar este comportamiento, o para proporcionar un valor predeterminado en caso de filas que faltan. Además, el mensaje de error no es muy explicativo (podría ser útil publicar un informe de error aquí).

p.s. dado que csv2rec guarda el contenido del archivo en un registro numpy, será más fácil obtener los valores iguales a None.

Cuestiones relacionadas