15

Python でカスタムquotingを定義する方法を探しています。csv.writer値をクォートする組み込みの方法が 4 つあります。

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

ただし、Postgres をエミュレートする引用メカニズムが必要FORCE QUOTE *です。つまり、None 以外のすべての値を引用します。csv.QUOTE_ALLPython を使用すると None になり''ますが、代わりに空の文字列が必要です。

組み込みcsvモジュールでそれを行うことは可能ですか (私はハックには興味がありません、私はすでにそれをやっています:P)? または、カスタム csv パーサーを作成/取得する必要がありますか?

csvそして一般的に:モジュールのカスタム引用メカニズムを書くことは可能ですか?

4

2 に答える 2

14

引用を無効csvにして、自分で引用を追加します。

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

との両方を空の文字列に設定escapecharするquotecharことで、モジュールが既に引用されている値を引用することを回避できます。

上記は、csv 値で区切り記号を使用しない限り機能します。

この時点で、コンマ区切りの行を自分で書く方が簡単になることに注意してください。

with open(filename, 'w'), fd:
    for row in rows:
        fd.write(','.join(map(quote, row)) + '\r\n')
于 2013-10-11T10:15:11.030 に答える
8

私は自分がやりたいことを正確に行う独自の csv ライターを作成しました。

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)

誰かが問題を見つけたら、私に知らせてください。csvただし、モジュールを使用したソリューションをまだ探しています。

于 2013-10-11T10:40:58.097 に答える