Як записати дані у формат CSV як рядок (не файл)?


119

Я хочу передати такі дані, як [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')

2
У Python 3 StringIO()знаходиться в ioбібліотеці.
Арістід

Відповіді:


66

Ви можете використовувати StringIOзамість власного Dummy_Writer:

Цей модуль реалізує файлоподібний клас, StringIOякий читає і записує буфер рядків (також відомий як файли пам'яті).

Є також cStringIO, яка є більш швидкою версією StringIOкласу.


164

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

Хороший приклад. :) Що стосується бічної сторони, яка звична поведінка при зустрічі з новими рядками всередині файлу CSV? Чи \nдобре мати посеред даних, але \r\nвказує на кінець запису, незалежно від того, де вона з’являється? (Припустимо, що ви перебуваєте на платформі, яка використовує \r\nяк термінатор лінії.)
Li-aung Yip

2
Потрібно output = StringIO.StringIO(), io.StringIO()підніме TypeError: очікується аргумент рядка, отримано 'str'.
Марбоні

2
@Marboni: StringIO відсутній у Python 3 (саме так написано моє рішення), і я не можу відтворити цю помилку в Python 2.7.3 - хоча я отримую TypeError у writer.writerow(...)рядку ( unicode argument expected, got 'str'). Розберемося в цьому.
Тім Піцкер

1
@Marboni: Дякую за голову: я знайшов проблему за допомогою StackOverflow. У Python 2 вам потрібно io.BytesIO()замість io.StringIO().
Тім Піцкер

1
@Marboni: У Python 2.7.9 він працює зі StringIO.StringIO () або io.BytesIO ().
srock

6

Я знайшов відповіді, загалом, трохи заплутаними. Для 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)

2

оскільки я використовую це досить багато для того, щоб асинхронно передавати результати з 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: джерело та тест


0
import csv
from StringIO import StringIO
with open('file.csv') as file:
    file = file.read()

stream = StringIO(file)

csv_file = csv.DictReader(stream)

3
Відповіді, що стосуються лише коду, не рекомендують відповісти на роз'яснення
Raniz

-1

Ось версія, яка працює для 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()
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.