2013-10-11 13 views
10

Szukam sposobu zdefiniowania niestandardowego quoting z csv.writer w języku Python. Istnieją 4 wbudowane sposoby qoute wartości:Pisarz CSV w Pythonie z niestandardowym cytowaniem

csv.QUOTE_ALL, csv.QUOTE_MINIMAL, csv.QUOTE_NONNUMERIC, csv.QUOTE_NONE 

Jednak muszę się powołując się mechanizm, który będzie naśladować Postgres' FORCE QUOTE *, to będzie to cytowanie wszystkie wartości non-None. Z csv.QUOTE_ALL Python zmieni None na '', ale zamiast tego chciałbym mieć pusty ciąg.

Czy można to zrobić z wbudowanym modułem csv (nie interesują mnie hacki, już to robię: P)? Czy jestem zmuszony do napisania/pobrania jakiegoś niestandardowego parsera csv?

I ogólnie: czy można napisać niestandardowy mechanizm cytowania dla modułu csv?

Odpowiedz

9

Wyłącz csv cytowanie i dodać cytaty siebie:

def quote(col): 
    if col is None: 
     return '' 
    # uses double-quoting style to escape existing quotes 
    return '"{}"'.format(str(col).replace('"', '""')) 

writer = csv.writer(fileobj, quoting=csv.QUOTE_NONE, escapechar='', quotechar='') 

for row in rows: 
    writer.writerow(map(quote, row)) 

Poprzez ustawienie zarówno escapechar i quotechar opróżnić ciągów uniknąć moduł podając już notowanych wartości.

Powyższe działa tak długo, jak nie używasz ogranicznika w wartościach csv.

Należy zauważyć, że w tym czasie byłoby to po prostu łatwiej napisać rozdzielany przecinkami linii siebie:

with open(filename, 'w'), fd: 
    for row in rows: 
     fd.write(','.join(map(quote, row)) + '\r\n') 
+1

Już próbowałeś: problem polega na tym, że musisz podać 'escapechar' za pomocą' QUOTE_NONE', a następnie wymazuje on cytaty. – freakish

+0

@freakish: tylko jeśli 'quotechar' jest nadal ustawiony. –

+0

Domyślnie jest to "", czyż nie? – freakish

4

Pisałem własne pisarza csv, który robi dokładnie to, co chcę:

class PostgresCSVWriter(object): 
    def __init__(self, stream, quotechar="\"", delimiter=",", escapechar="\\"): 
     self.stream = stream 
     self.quotechar = quotechar 
     self.delimiter = delimiter 
     self.escapechar = escapechar 
     self.buffer_size = 16384 

    def _convert_value(self, obj): 
     if obj is None: 
      return "" 
     value = str(obj) 
     value = value.replace(self.quotechar, self.quotechar+self.quotechar) 
     value = value.replace(self.delimiter, self.escapechar+self.delimiter) 
     return self.quotechar+value+self.quotechar 

    def _convert_row(self, row): 
     return self.delimiter.join(self._convert_value(v) for v in row) + "\r\n" 

    def writerow(self, row): 
     self.stream.write(self._convert_row(row)) 

    def writerows(self, rows): 
     data = "" 
     counter = 0 
     for row in rows: 
      buf = self._convert_row(row) 
      data += buf 
      counter += len(buf) 
      if counter >= self.buffer_size: 
       self.stream.write(data) 
       data = "" 
       counter = 0 

     if data: 
      self.stream.write(data) 

Jeśli ktoś zauważy jakikolwiek problem, proszę dać mi znać. Wciąż szukam rozwiązania z modułem csv.

Powiązane problemy