Làm cách nào để ghi dữ liệu vào định dạng CSV dưới dạng chuỗi (không phải tệp)?


119

Tôi muốn truyền dữ liệu [1,2,'a','He said "what do you mean?"']sang một chuỗi có định dạng CSV.

Thông thường người ta sẽ sử dụng csv.writer()cho điều này, bởi vì nó xử lý tất cả các trường hợp cạnh điên rồ (thoát dấu phẩy, thoát dấu ngoặc kép, phương ngữ CSV, v.v.) Bắt được csv.writer()mong đợi xuất ra đối tượng tệp chứ không phải chuỗi.

Giải pháp hiện tại của tôi là chức năng hơi hack này:

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

Bất cứ ai có thể đưa ra một giải pháp thanh lịch hơn mà vẫn xử lý tốt các trường hợp cạnh?

Chỉnh sửa: Đây là cách tôi đã thực hiện nó:

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

2
Trong Python 3, StringIO()nằm trong iothư viện.
Aristide

Câu trả lời:


67

Bạn có thể sử dụng StringIOthay vì của riêng bạn Dummy_Writer:

Mô-đun này thực hiện một lớp giống như tệp StringIO, đọc và ghi một bộ đệm chuỗi (còn được gọi là tệp bộ nhớ).

Ngoài ra còn có cStringIO, là phiên bản nhanh hơn của StringIOlớp.


165

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

Một số chi tiết cần được thay đổi một chút cho 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'

Ví dụ tốt. :) Là một phụ chú, hành vi thông thường khi gặp các dòng mới bên trong tệp CSV là gì? Có được không \nkhi có dữ liệu ở giữa, nhưng \r\nchỉ ra phần cuối của bản ghi bất kể nó xuất hiện ở đâu? (Giả sử bạn đang ở trên một nền tảng mà sử dụng \r\nnhư dòng terminator.)
Li-Aung Yip

2
Nên output = StringIO.StringIO(), io.StringIO()sẽ nâng lên TypeError: đối số chuỗi được mong đợi, có 'str'.
Marboni 29/10/12

2
@Marboni: StringIO đã biến mất trong Python 3 (đó là giải pháp của tôi được viết bằng) và tôi không thể tạo lại lỗi đó trong Python 2.7.3 - mặc dù tôi nhận được TypeError trong writer.writerow(...)dòng ( unicode argument expected, got 'str'). Sẽ xem xét điều này.
Tim Pietzcker 29/10/12

1
@Marboni: Cảm ơn bạn đã lưu ý: Tôi đã tìm thấy sự cố với sự trợ giúp của StackOverflow. Trong Python 2, bạn cần io.BytesIO()thay vì io.StringIO().
Tim Pietzcker 29/10/12

1
@Marboni: Trong Python 2.7.9, nó hoạt động với StringIO.StringIO () hoặc io.BytesIO ().
srock

6

Tôi đã tìm thấy câu trả lời, nói chung, hơi khó hiểu. Đối với Python 2, cách sử dụng này phù hợp với tôi:

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

vì tôi sử dụng điều này khá nhiều để truyền kết quả không đồng bộ từ sanic trở lại người dùng dưới dạng dữ liệu csv nên tôi đã viết đoạn mã sau cho Python 3 .

Đoạn mã cho phép bạn sử dụng lại cùng một vùng đệm StringIo nhiều lần.


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"

thí dụ:

csv_formatter = ArgsToCsv()

output += csv_formatter.stringify(
    10,
    """
    lol i have some pretty
    "freaky"
    strings right here \' yo!
    """,
    [10, 20, 30],
)

Kiểm tra cách sử dụng thêm tại github gist: source and test


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
Câu trả lời mã chỉ được nản chí, bạn nên thêm một số giải thích cho câu trả lời của bạn
Raniz

-1

Đây là phiên bản hoạt động cho utf-8. csvline2string chỉ cho một dòng, không có dấu ngắt dòng ở cuối, csv2string cho nhiều dòng, có dấu ngắt dòng:

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()
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.