파일이 아닌 문자열로 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
파이썬 3에서, StringIO()에있는 io라이브러리입니다.
Aristide 2019 년

답변:


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. 라인 종결 자로가)
깨갱 리튬 아웅

2
이어야합니다 output = StringIO.StringIO(). io.StringIO()TypeError : string 인수가 예상되고 'str'이 발생합니다.
Marboni

2
@Marboni : StringIO는 Python 3 (내 솔루션이 작성된 것임)에서 사라졌고 Python 2.7.3에서 해당 오류를 재현 할 수 없습니다 . writer.writerow(...)( unicode argument expected, got 'str') 줄에 TypeError가 발생하더라도 . 이것을 조사 할 것입니다.
Tim Pietzcker 2012 년

1
@Marboni : 미리 알려 주셔서 감사합니다 . StackOverflow의 도움으로 문제발견했습니다 . 파이썬이, 당신은 필요 io.BytesIO()가 아닌 io.StringIO().
Tim Pietzcker 2012 년

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 gist에서 추가 사용법 확인 : 소스 및 테스트


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()
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.