2012-02-06 9 views
61

Chcę przesyłać dane takie jak [1,2,'a','He said "what do you mean?"'] do ciągu w formacie CSV.Jak zapisać dane w formacie csv jako ciąg (nie plik)?

Normalnie można by użyć csv.writer() dla tego, ponieważ obsługuje wszystkie szalone przypadków brzegowych (przecinek ucieczce cudzysłów ucieczce dialektów CSV, itp) Połów jest, że csv.writer() oczekuje na wyjście z obiektu pliku, a nie do strunowy.

Moje obecne rozwiązanie jest to nieco hacky funkcja:

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 

Czy ktoś może dać bardziej eleganckie rozwiązanie, które nadal obsługuje przypadki brzegowe dobrze?

Edycja: Oto jak skończyło się to robi:

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

Odpowiedz

39

Można użyć StringIO zamiast własnego Dummy_Writer:

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

Istnieje również cStringIO, która jest szybsza wersja StringIO klasa.

79

W Pythonie 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' 

Niektóre dane muszą być zmieniane trochę dla Pythona 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

Dobry przykład. :) Jak zwykle, jakie jest zwyczajowe zachowanie podczas napotykania znaków nowej linii w pliku CSV? Czy "\ n" jest w porządku w środku danych, ale '\ r \ n' wskazuje koniec rekordu bez względu na to, gdzie się pojawi? (Zakładając, że jesteś na platformie, która używa '\ r \ n' jako terminatora linii.) –

+0

Nie jestem pewien. Sam bym się spodziewał '\ r \ n', ponieważ domyślnym parametrem dla' io.StringIO() 'jest' newline = None', który włącza tryb uniwersalnych znaków nowej linii, który powinien automatycznie używać poprawnego stylu linii nowej linii w zależności od platformy. Sam jestem trochę zaskoczony tym zachowaniem. –

+0

@ Li-aungYip: Otworzyłem [pytanie na ten temat] (http://stackoverflow.com/questions/9157623/unexpected-behavior-of-universal-newline-mode-with-stringio-and-csv-modules). –

0

Oto wersja, która działa na UTF-8. csvline2string tylko dla jednej linii, bez podziału wierszy na końcu, csv2string na wielu liniach, z wierszami:

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

Odradza się odpowiedzi dotyczące wyłącznie kodu, należy dodać jakieś wyjaśnienie do swojej odpowiedzi – Raniz

1

znalazłem odpowiedzi, w sumie, nieco mylące. W przypadku Pythona 2 to użycie zadziałało:

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) 
Powiązane problemy