Vraag CSV-schrijver in Python met aangepaste citaten


Ik ben op zoek naar een manier om maatwerk te definiëren quoting met csv.writer in Python. Er zijn 4 ingebouwde manieren om waarden te qoute:

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

Ik heb echter een citeermechanisme nodig dat Postgres zal nabootsen FORCE QUOTE *, d.w.z. het zal alle niet-geen-waarden vermelden. Met csv.QUOTE_ALL Python zal None veranderen in '' maar ik zou in plaats daarvan een lege string willen hebben.

Is het mogelijk om dat met ingebouwde te doen csv module (ik ben niet geïnteresseerd in hacks, ik doe dat al: P)? Of ben ik gedwongen om een ​​aangepaste CSV-parser te schrijven / te krijgen?

En in het algemeen: is het mogelijk om een ​​eigen citeermechanisme voor te schrijven csv module?


11
2017-10-11 09:59


oorsprong


antwoorden:


onbruikbaar maken csv citeren en zelf citaten toevoegen:

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

Door beide in te stellen escapechar en quotechar om strings te legen vermijd je de module met citaten van je reeds geciteerde waarden.

Het bovenstaande werkt zolang u de. Niet gebruikt scheidingsteken in de csv-waarden.

Merk op dat het tegen die tijd eenvoudiger zou zijn om door komma's gescheiden regels zelf te schrijven:

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

10
2017-10-11 10:15



Ik heb mijn eigen csv-schrijver geschreven die precies doet wat ik wil:

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)

Als iemand een probleem ziet, laat het me dan weten. Ik ben nog steeds op zoek naar een oplossing met csv module wel.


5
2017-10-11 10:40