csv writer in Python with custom quoting

前端 未结 2 1618
心在旅途
心在旅途 2020-12-16 15:54

I\'m looking for a way to define custom quoting with csv.writer in Python. There are 4 built-in ways to qoute values:

csv.QUOTE_ALL         


        
相关标签:
2条回答
  • 2020-12-16 16:43

    Disable csv quoting and add the quotes yourself:

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

    By setting both escapechar and quotechar to empty strings you avoid the module quoting your already-quoted values.

    The above works as long as you don't use the delimiter in the csv values.

    Note that by this time it would just be easier to write comma-delimited lines yourself:

    with open(filename, 'w'), fd:
        for row in rows:
            fd.write(','.join(map(quote, row)) + '\r\n')
    
    0 讨论(0)
  • 2020-12-16 16:47

    I've written my own csv writer which does exactly what I want:

    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)
    

    If anyone sees any problem with it, then please let me know. I'm still looking for a solution with csv module though.

    0 讨论(0)
提交回复
热议问题