2012-02-07 26 views
6

me gustaría usar pitón leer y escribir archivos de la siguiente forma:Lectura de texto con formato utilizando Python

#h -F, field1 field2 field3 
a,b,c 
d,e,f 
# some comments 
g,h,i 

Este archivo se parece mucho a un CSV típica, con las siguientes excepciones:

  1. El la línea del encabezado comienza con #h
  2. El segundo elemento de la línea del encabezado es una etiqueta para indicar el delimitador
  3. Los demás elementos del encabezado son nombres de campo (siempre separados por un solo espacio)
  4. Las líneas de comentario siempre comienzan con # y pueden estar dispersos en todo el archivo

¿Hay alguna manera de que pueda utilizar csv.DictReader() y csv.DictWriter() para leer y escribir estos archivos ?

+0

¿Has probado subclasificar las clases existentes y agregar el comportamiento extra? – IanGilham

+0

comentario sólo parte: http://stackoverflow.com/questions/14158868/python-skip-comment-lines-marked-with-in-csv-dictreader –

Respuesta

8

puede analizar por separado la primera línea para encontrar el delimitador y nombres de campos:

firstline = next(f).split() 
    delimiter = firstline[1][-1] 
    fields = firstline[2:] 

Tenga en cuenta que csv.DictReader puede tomar cualquier iterable como primer argumento. Así que saltarse las observaciones, se puede envolver f en un iterador (skip_comments) que produce sólo las líneas no comment:

import csv 
def skip_comments(iterable): 
    for line in iterable: 
     if not line.startswith('#'): 
      yield line 

with open('data.csv','rb') as f: 
    firstline = next(f).split() 
    delimiter = firstline[1][-1] 
    fields = firstline[2:] 
    for line in csv.DictReader(skip_comments(f), 
           delimiter = delimiter, fieldnames = fields): 
     print line 

en los datos que ha publicado esto produce

{'field2': 'b', 'field3': 'c', 'field1': 'a'} 
{'field2': 'e', 'field3': 'f', 'field1': 'd'} 
{'field2': 'h', 'field3': 'i', 'field1': 'g'} 

Para escribir un archivo en este formato, se podría utilizar una función header ayudante:

def header(delimiter,fields): 
    return '#h -F{d} {f}\n'.format(d = delimiter, f=' '.join(fields)) 

with open('data.csv', 'rb') as f: 
    with open('output.csv', 'wb') as g: 
     firstline = next(f).split() 
     delimiter = firstline[1][-1] 
     fields = firstline[2:] 
     writer = csv.DictWriter(g, delimiter = delimiter, fieldnames = fields) 
     g.write(header(delimiter,fields)) 
     for row in csv.DictReader(skip_comments(f), 
            delimiter = delimiter, fieldnames = fields): 
      writer.writerow(row) 
      g.write('# comment\n') 

Tenga en cuenta que puede escribir al output.csv usando g.write (para encabezado o líneas de comentario) o writer.writerow (para csv).

+0

Agradable. Ahora supongamos que quiero escribir en un archivo usando este formato cuasi-CSV (es decir, usando las cuatro peculiaridades mencionadas en la pregunta). ¿Cómo usaría csv.DictWriter para hacer eso? – Dave

0

Supongamos que el archivo de entrada se abre como input. En primer lugar, leer en la cabecera:

header = input.readline() 

omita los nombres y delimitadores de campo y usarlo para construir una DictReader. Ahora, en lugar de input, alimentar al lector la expresión

(ln for ln in input where ln[0] != '#') 

saltarse los comentarios.

Cuestiones relacionadas