2012-02-06 13 views
61

Voglio trasmettere dati come [1,2,'a','He said "what do you mean?"'] a una stringa in formato csv.Come posso scrivere i dati in formato csv come stringa (non file)?

Normalmente si potrebbe usare csv.writer() per questo, perché gestisce tutti i casi limite folli (virgola fuga, segno di citazione in fuga, dialetti CSV, ecc) Il problema è che csv.writer() prevede di output in un oggetto file, non a un stringa.

mia soluzione attuale è questa funzione un po 'hacky:

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 

Qualcuno può dare una soluzione più elegante che gestisce ancora i casi limite bene?

Edit: Ecco come ho finito per farlo:

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

risposta

39

Si potrebbe utilizzare StringIO al posto della propria Dummy_Writer:

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

C'è anche cStringIO, che è una versione più veloce del StringIO classe.

79

In 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' 

Alcuni dettagli devono essere cambiato un po 'per 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

Buon esempio. :) Come sidenote, qual è il comportamento normale quando si incontrano nuove righe all'interno di un file CSV? '\ N' ok avere nel mezzo dei dati, ma' \ r \ n' indica la fine di un record, non importa dove appare? (Supponendo che tu sia su una piattaforma che utilizza '\ r \ n' come terminatore di riga.) –

+0

Non sono sicuro. Mi sarei aspettato '\ r \ n' perché il parametro predefinito per' io.StringIO() 'è' newline = None' che abilita la modalità newlines universale, che dovrebbe utilizzare automaticamente lo stile newline corretto in base alla piattaforma. Sono un po 'perplesso da questo comportamento me stesso. –

+0

@ Li-aungYip: ho aperto una [domanda a riguardo] (http://stackoverflow.com/questions/9157623/unexpected-behavior-of-universal-newline-mode-with-stringio-and-csv-modules). –

0

Ecco la versione che funziona per utf-8. csvline2string per una sola riga, senza interruzioni di linea, alla fine, csv2string per molte linee, con interruzioni di linea:

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

Le risposte solo in codice sono scoraggiate, è necessario aggiungere qualche chiarimento alla risposta – Raniz

1

ho trovato le risposte, tutto sommato, un po 'di confusione. Per Python 2, questo utilizzo ha funzionato per me:

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