2009-01-30 12 views
10

Estoy escribiendo una utilidad de Python que necesita analizar un gran archivo CSV regularmente actualizado que no controlo. La utilidad debe ejecutarse en un servidor con solo Python 2.4 disponible. El archivo CSV no cita valores de campo en absoluto, pero el Python 2.4 version of the csv library no parece darme ninguna manera de desactivar las comillas, solo me permite establecer el carácter de comillas (dialect.quotechar = '"' o lo que sea). Si intento configurar el carácter de cita en None o en la cadena vacía, aparece un error.¿Cómo puedo desactivar las citas en el lector Python 2.4 CSV?

Puedo trabajar alrededor de esto configurando dialect.quotechar en algún carácter "raro", pero esto es frágil, ya que no hay caracteres ASCII, puedo garantizar que no aparecerán en los valores de campo (excepto el delimitador, pero si Configuré dialect.quotechar = dialect.delimiter, las cosas se vuelven impredecibles).

En Python 2.5 and later, si configuro dialect.quoting en csv.QUOTE_NONE, el lector CSV respeta eso y no interpreta ningún carácter como carácter de comillas. ¿Hay alguna forma de duplicar este comportamiento en Python 2.4?

ACTUALIZACIÓN: Gracias Tripadvisor y Mark Roddy por ayudar a reducir el problema. Aquí está una demostración más simple de los casos:

>>> import csv 
>>> import StringIO 
>>> data = """ 
... 1,2,3,4,"5 
... 1,2,3,4,5 
... """ 
>>> reader = csv.reader(StringIO.StringIO(data)) 
>>> for i in reader: print i 
... 
[] 
Traceback (most recent call last): 
    File "<stdin>", line 1, in ? 
_csv.Error: newline inside string 

El problema sólo se produce cuando hay un solo carácter de comillas dobles en la final de la columna de una fila. Lamentablemente, esta situación existe en mi conjunto de datos. He aceptado la solución de Tanj: asigne manualmente un carácter no imprimible ("\x07" o BEL) como la carátula. Esto es chiflado, pero funciona, y todavía no he visto otra solución que lo haga. He aquí una demostración de la solución en acción:

>>> import csv 
>>> import StringIO 
>>> class MyDialect(csv.Dialect): 
...  quotechar = '\x07' 
...  delimiter = ',' 
...  lineterminator = '\n' 
...  doublequote = False 
...  skipinitialspace = False 
...  quoting = csv.QUOTE_NONE 
...  escapechar = '\\' 
... 
>>> dialect = MyDialect() 
>>> data = """ 
... 1,2,3,4,"5 
... 1,2,3,4,5 
... """ 
>>> reader = csv.reader(StringIO.StringIO(data), dialect=dialect) 
>>> for i in reader: print i 
... 
[] 
['1', '2', '3', '4', '"5'] 
['1', '2', '3', '4', '5'] 

En Python 2.5+ entorno citando a csv.QUOTE_NONE sería suficiente, y el valor de quotechar entonces sería irrelevante. (De hecho, estoy obteniendo mi dialecto inicial a través de csv.Sniffer y luego anulando el valor de la cita, no subclasificando csv.Dialect, pero no quiero que eso sea una distracción del problema real; las dos sesiones anteriores demuestran que Sniffer no está el problema.)

Respuesta

12

No sé si Python le gustaría/lo permitiría pero podría usar un código ascii no imprimible como BEL o BS (retroceso) Estos me parecerían extremadamente raros.

+0

Vaya, buena idea. Establecer csv.quotechar = '\ x07' (BEL) parece hacer el truco. No puedo imaginar cómo podrían obtener eso en sus datos CSV. –

+1

Haha - buen truco. :-) – cdleary

+0

Agradable, hacktastic. – Kiv

3

Probé algunos ejemplos usando Python 2.4.3, y me pareció lo suficientemente inteligente como para detectar que los campos no se habían citado.

Sé que ya has aceptado una respuesta (ligeramente hacky), pero ¿has intentado simplemente dejar el valor de reader.dialect.quotechar solo? que pasa si tu lo haces?

¿Alguna posibilidad de que podamos obtener una entrada de ejemplo?

+0

Todavía estoy interesado en un enfoque menos hacky, si es que hay uno. Puedo obtener algunos ejemplos de entrada cargados pronto. El dialecto que estoy usando es generado por un objeto csv.Sniffer (necesito ser lo más robusto posible contra los cambios de formato). Si dejo el cuasar solo, aparece el valor predeterminado para comillas dobles '' ''. –

0

1 para Tríptico

La confirmación de que csv.reader maneja automáticamente los archivos CSV con citas fuera:

>>> import StringIO 
>>> import csv 
>>> data=""" 
... 1,2,3,4,5 
... 1,2,3,4,5 
... 1,2,3,4,5 
... """ 
>>> reader=csv.reader(StringIO.StringIO(data)) 
>>> for i in reader: 
...  print i 
... 
[] 
['1', '2', '3', '4', '5'] 
['1', '2', '3', '4', '5'] 
['1', '2', '3', '4', '5'] 
+0

Esto no es realmente una prueba relevante, ya que no importa a qué tipo de citas se establezca, el presupuesto es opcional; puede manejar campos sin comillas bien. es cuando el quotechar aparece en los datos, y aparentemente, solo cuando aparece en la columna final. Gracias por empujarme a reducirlo. –

Cuestiones relacionadas