2012-02-07 23 views
6

Chciałbym użyć Pythona odczytywać i zapisywać pliki w następującym formacie:Reading sformatowany tekst przy użyciu Pythona

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

Plik ten przypomina typową CSV, z wyjątkiem następujących:

  1. The linia nagłówka zaczyna się od #h
  2. Drugi element linii nagłówka to znacznik określający separator
  3. Pozostałe elementy nagłówka to nazwy pól (zawsze oddzielone od siebie pojedyncza spacja)
  4. Linie komentarza zawsze zaczynają się od znaku # i mogą być rozproszone po całym pliku

Czy jest jakiś sposób mogę korzystać csv.DictReader() i csv.DictWriter() do odczytu i zapisu tych plików ?

+0

Czy próbowałeś podklasować istniejące klasy i dodać dodatkowe zachowanie? – IanGilham

+0

tylko część komentarza: http://stackoverflow.com/questions/14158868/python-skip-comment-lines-marked-with-in-csv-dictreader –

Odpowiedz

8

Można analizować pierwszą linię osobno znaleźć separatora i fieldnames:

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

Zauważ, że csv.DictReader zniosę iterable jako pierwszy argument. Tak aby pominąć komentarze, można owinąć f w iterator (skip_comments) co daje tylko linie bez komentarza:

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 

Z danych, które pisał ten daje

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

Aby napisać plik w tym formacie, można użyć funkcji pomocniczej header:

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

Zauważ, że możesz napisać do output.csv używając g.write (dla linii nagłówka lub komentarza) lub writer.writerow (dla csv).

+0

Nice. Teraz przypuśćmy, że chcę napisać do pliku przy użyciu tego quasi-formatu CSV (tj. Używając czterech osobliwości wymienionych w pytaniu). W jaki sposób mogę użyć csv.DictWriter, aby to zrobić? – Dave

0

Założono, że plik wejściowy jest otwarty jako input. Po pierwsze, czytamy w nagłówku:

header = input.readline() 

Przetwarza się nazwy ogranicznika i polowych i używać, aby skonstruować DictReader. Teraz, zamiast input, należy przekazać czytnikowi wyrażenie, aby pominąć komentarze.

Powiązane problemy