ฉันจะเขียนข้อมูลในรูปแบบ CSV เป็นสตริง (ไม่ใช่ไฟล์) ได้อย่างไร


119

ฉันต้องการแคสต์ข้อมูลเช่นเดียว[1,2,'a','He said "what do you mean?"']กับสตริงที่มีรูปแบบ CSV

โดยปกติจะใช้csv.writer()สำหรับสิ่งนี้เพราะมันจัดการกับกรณี edge ที่บ้าคลั่งทั้งหมด (การหลบหนีด้วยลูกน้ำ, เครื่องหมายอัญประกาศ, ภาษาถิ่น 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ไลบรารี
Aristide

คำตอบ:


67

คุณสามารถใช้StringIOแทนของคุณเองDummy_Writer:

โมดูลนี้ใช้คลาสเหมือนไฟล์StringIOซึ่งอ่านและเขียนสตริงบัฟเฟอร์ (หรือที่เรียกว่าไฟล์หน่วยความจำ)

นอกจากนี้ยังมีcStringIOซึ่งเป็นรุ่นที่เร็วกว่าของStringIOคลาส


165

ใน 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'
Marboni

2
@Marboni: StringIO หายไปใน Python 3 (ซึ่งเป็นสิ่งที่วิธีแก้ปัญหาของฉันเขียนไว้) และฉันไม่สามารถสร้างข้อผิดพลาดนั้นใน Python 2.7.3 ได้ - แม้ว่าฉันจะได้รับ TypeError ในwriter.writerow(...)บรรทัด ( unicode argument expected, got 'str') จะดูในเรื่องนี้
Tim Pietzcker

1
@Marboni: ขอบคุณสำหรับการแจ้งเตือน: ฉันพบปัญหาด้วยความช่วยเหลือของ StackOverflow ใน Python 2 คุณต้องio.BytesIO()ใช้แทนio.StringIO()ไฟล์.
Tim Pietzcker

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 ผมเขียนข้อมูลต่อไปนี้สำหรับหลาม 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 and test



-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.