Как мне записать данные в формате CSV в виде строки (не файл)?
Я хочу привести данные как [1,2,'a','He said "what do you mean?"']
в строку в формате CSV.
Обычно можно использовать csv.writer()
для этого, потому что он обрабатывает все безумные крайние случаи (экранирование запятой, экранирование кавычек, диалекты CSV и т. д.) csv.writer()
ожидает вывода в файловый объект, а не в строку.
Мое текущее решение - это несколько хакерская функция:
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
Кто-нибудь может дать более элегантное решение, которое по-прежнему хорошо обрабатывает крайние случаи?
Редактировать: вот как я закончил делать это:
def csv2string(data):
si = StringIO.StringIO()
cw = csv.writer(si)
cw.writerow(data)
return si.getvalue().strip('\r\n')
5 ответов
Вы могли бы использовать StringIO
вместо твоего собственного Dummy_Writer
:
Этот модуль реализует файловый класс,
StringIO
, который читает и записывает строковый буфер (также известный как файлы памяти).
Существует также cStringIO
, которая является более быстрой версией StringIO
учебный класс.
В 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'
Некоторые детали должны быть немного изменены для 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'
Так как я довольно часто использую это для асинхронной потоковой передачи результатов от sanic обратно к пользователю в виде данных csv, я написал следующий фрагмент для Python 3.
Этот фрагмент позволяет повторно использовать один и тот же буфер StringIo снова и снова.
import csv
from io import StringIO
class ArgsToCsv:
def __init__(self, seperator=","):
self.seperator = seperator
self.buffer = StringIO()
self.writer = csv.writer(self.buffer)
def stringify(self, *args):
self.writer.writerow(args)
value = self.buffer.getvalue().strip("\r\n")
self.buffer.seek(0)
self.buffer.truncate(0)
return value + "\n"
пример:
csv_formatter = ArgsToCsv()
output += csv_formatter.stringify(
10,
"""
lol i have some pretty
"freaky"
strings right here \' yo!
""",
[10, 20, 30],
)
Ознакомьтесь с дальнейшим использованием на github gist: source и test
Я нашел ответы, в целом, немного запутанным. Для Python 2 это использование работало для меня:
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)
Поскольку ваш пример имеет только одну строку данных, вы можете просто использовать
input = [1,2,'a','He said "what do you mean?"']
output = ",".join(str(x) for x in input)
Очевидно, что если входные данные имеют более сложную форму, такую как словарь или двумерный массив, этот простой ответ станет более сложным.
import csv
from StringIO import StringIO
with open('file.csv') as file:
file = file.read()
stream = StringIO(file)
csv_file = csv.DictReader(stream)
Вот версия, которая работает для UTF-8. csvline2string только для одной строки, без разрывов строк в конце, csv2string для многих строк, с разрывами строк:
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()