python - guia - qgis manual
escritor csv en Python con citas personalizadas (2)
Estoy buscando una forma de definir csv.writer
personalizados con csv.writer
en Python. Hay 4 formas integradas de valores de qoute:
csv.QUOTE_ALL, csv.QUOTE_MINIMAL, csv.QUOTE_NONNUMERIC, csv.QUOTE_NONE
Sin embargo, necesito un mecanismo de cotización que emule el '' FORCE QUOTE *
Postgres, es decir, citará todos los valores que no sean None. Con csv.QUOTE_ALL
Python convertirá None en ''''
pero me gustaría tener una cadena vacía en su lugar.
¿Es posible hacer eso con el módulo csv
incorporado (no estoy interesado en hacks, ya estoy haciendo eso: P)? ¿O me veo obligado a escribir / obtener algún analizador csv personalizado?
Y en general: ¿es posible escribir un mecanismo de cotización personalizado para el módulo csv
?
Desactive las citas csv
y agregue las cotizaciones usted mismo:
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))
Al configurar tanto escapechar
como quotechar
en cadenas vacías, se evita el módulo que cita los valores ya citados.
Lo anterior funciona siempre que no uses el delimitador en los valores csv.
Tenga en cuenta que, para entonces, simplemente sería más fácil escribir líneas delimitadas por comas usted mismo:
with open(filename, ''w''), fd:
for row in rows:
fd.write('',''.join(map(quote, row)) + ''/r/n'')
Escribí mi propio escritor de csv que hace exactamente lo que quiero:
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)
Si alguien ve algún problema con él, por favor avíseme. Todavía estoy buscando una solución con módulo csv
.