2012-02-06 13 views
61

Quiero transmitir datos como [1,2,'a','He said "what do you mean?"'] a una cadena con formato csv.¿Cómo escribo datos en formato csv como cadena (no archivo)?

Normalmente se usaría csv.writer() para esto, ya que maneja todos los casos extremos locos (coma escapar, escapar comillas, dialectos CSV, etc.) El problema es que csv.writer() espera a la salida a un objeto de archivo, no a una cuerda.

Mi solución actual es un poco hacky esta función:

def CSV_String_Writeline(data): 
    class Dummy_Writer: 
     def write(self,instring): 
      self.outstring = instring.strip("\r\n") 
    dw = Dummy_Writer() 
    csv_w = csv.writer(dw) 
    csv_w.writerow(data) 
    return dw.outstring 

Puede alguien dar una solución más elegante que todavía se maneja bien los casos extremos?

Editar: Esto es como terminé haciéndolo:

def csv2string(data): 
    si = StringIO.StringIO() 
    cw = csv.writer(si) 
    cw.writerow(data) 
    return si.getvalue().strip('\r\n') 

Respuesta

39

usted podría utilizar StringIO en lugar de su propia Dummy_Writer:

This module implements a file-like class, StringIO , that reads and writes a string buffer (also known as memory files).

Existe también cStringIO, que es una versión más rápida de la StringIO clase.

79

En Python 3:

>>> import io 
>>> import csv 
>>> output = io.StringIO() 
>>> csvdata = [1,2,'a','He said "what do you mean?"',"Whoa!\nNewlines!"] 
>>> writer = csv.writer(output, quoting=csv.QUOTE_NONNUMERIC) 
>>> writer.writerow(csvdata) 
59 
>>> output.getvalue() 
'1,2,"a","He said ""what do you mean?""","Whoa!\nNewlines!"\r\n' 

Algunos detalles tienen que ser modificado un poco para Python 2:

>>> output = io.BytesIO() 
>>> writer = csv.writer(output) 
>>> writer.writerow(csvdata) 
57L 
>>> output.getvalue() 
'1,2,a,"He said ""what do you mean?""","Whoa!\nNewlines!"\r\n' 
+0

Buen ejemplo. :) Como nota al margen, ¿cuál es el comportamiento habitual al encontrar nuevas líneas dentro de un archivo CSV? ¿Está '\ n' bien en medio de los datos, pero' \ r \ n' indica el final de un registro, sin importar dónde aparezca? (Suponiendo que está en una plataforma que usa '\ r \ n' como el terminador de línea.) –

+0

No estoy seguro. Hubiera esperado '\ r \ n' yo mismo porque el parámetro predeterminado para' io.StringIO() 'es' newline = None' que habilita el modo de nuevas líneas universales, que debería usar automáticamente el estilo correcto de nueva línea según su plataforma. Estoy confundido por este comportamiento yo mismo. –

+0

@ Li-aungYip: He abierto una [pregunta sobre esto] (http://stackoverflow.com/questions/9157623/unexpected-behavior-of-universal-newline-mode-with-stringio-and-csv-modules) –

0

Aquí está la versión que funciona para UTF-8. csvline2string de una sola línea, sin saltos de línea al final, csv2string para muchas líneas, con saltos de línea:

import csv, io 

def csvline2string(one_line_of_data): 
    si = BytesIO.StringIO() 
    cw = csv.writer(si) 
    cw.writerow(one_line_of_data) 
    return si.getvalue().strip('\r\n') 

def csv2string(data): 
    si = BytesIO.StringIO() 
    cw = csv.writer(si) 
    for one_line_of_data in data: 
     cw.writerow(one_line_of_data) 
    return si.getvalue() 
-1
import csv 
from StringIO import StringIO 
with open('file.csv') as file: 
    file = file.read() 

stream = StringIO(file) 

csv_file = csv.DictReader(stream) 
+2

Se desaconsejan las respuestas de solo código, debe agregar algunas aclaraciones a su respuesta – Raniz

1

He encontrado las respuestas que, en general, un poco confuso. Para Python 2, este uso funcionó para mí:

import csv, io 

def csv2string(data): 
    si = io.BytesIO() 
    cw = csv.writer(si) 
    cw.writerow(data) 
    return si.getvalue().strip('\r\n') 

data=[1,2,'a','He said "what do you mean?"'] 
print csv2string(data) 
Cuestiones relacionadas