2013-10-11 24 views
10

Python'da ile csv.writer tanımlamak için bir yol arıyorum. Ben Postgres' FORCE QUOTE * taklit edecek bir alıntı mekanizmasını ihtiyaç Ancakcsv yazıcı

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

, yani tüm olmayan Yok değerlerini alıntı yapacağım: değerlerini qoute 4 yerleşik yolu vardır. csv.QUOTE_ALL Python, Yok'u '''a çevirecektir, ancak bunun yerine boş bir dizgi olmasını istiyorum.

Dahili csv modülüyle bunu yapmak mümkün mü (Ben hack ile ilgilenmiyorum, bunu zaten yapıyorum: P)? Ya da bazı özel csv ayrıştırıcısı yazmak/yazmak zorunda mıyım?

Ve genel olarak: csv modülü için özel teklif mekanizması yazmak mümkün mü?

cevap

9

Devre Dışı csv alıntı ve tırnak kendiniz ekleyin:

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

Eğer zaten alıntılanan değerleri alıntı modülünü önlemek dizeleri boşaltmak için hem escapechar ve quotechar ayarlayarak.

Yukarıdakiler, csv değerlerinde ayırıcıyı kullanmadığınız sürece çalışır. bu zamana kadar sadece virgülle ayrılmış satırları yazmak daha kolay olacağını

Not kendiniz: Ben tam yapar kendi csv yazar yazdım

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

Zaten bunu denedim: sorun, 'Qcapote_No' ile 'escapechar' belirtmek zorunda ve sonra tırnak işaretleri kaçar. – freakish

+0

@ freakish: sadece "quotechar" ayarlanmışsa. –

+0

Varsayılan olarak değil, " – freakish

4

ne istiyorum:

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) 

Birisi onunla herhangi bir sorun görürse, lütfen bana bildirin. Yine de csv modülüyle bir çözüm arıyorum.