簡體   English   中英

如何將帶有 unicode 數據的行轉換為 Py2 和 Py3 上的 latin-1 編碼的 csv 數據?

[英]How to convert rows with unicode data to latin-1 encoded csv data on Py2 and Py3?

我想將包含 Unicode 值的嵌套列表轉換為 latin-1 編碼的 csv(以便我可以在 Web 響應中傳輸結果並讓最終用戶的本地 Excel 打開文件)。

我們正在過渡到 Py3,因此最好是相同的代碼需要同時適用於 Py2 和 Py3(出於維護和覆蓋的原因)。

我們的 Python 2 代碼(適用於 py2):

from cStringIO import StringIO

def rows_to_csv_data(rows):
    rows = [[col.encode('latin-1') for col in row] for row in rows]
    buf = StringIO()
    writer = csv.writer(buf)
    writer.writerows(rows)
    return buf.getvalue()

一個簡單的測試用例:

def test_rows_to_csv_data():
    rows = [
        [u'helloæ', u'worldø']
    ]
    binary_data = rows_to_csv_data(rows)
    assert binary_data == u"helloæ,worldø\r\n".encode('latin-1')

    # Update: the data is never written to a file, but sent with a web response:
    response = http.HttpResponse(content_type='text/csv')
    response['Content-Disposition'] = 'attachment; filename=hello.csv'
    response.write(binary_data)
    assert response.serialize() == b'Content-Type: text/csv\r\nContent-Disposition: attachment; filename=hello.csv\r\n\r\nhello\xe6,world\xf8\r\n'

我找不到任何方便的方法來使用未來或六個庫來做到這一點。

使用from io import StringIO給我(Py3):

Expected :b'hello\xe6,world\xf8\r\n'
Actual   :b'hello\\xe6',b'world\\xf8'\r\n

和 Py2:

>       writer.writerows(rows)
E       TypeError: unicode argument expected, got 'str'

使用from io import BytesIO as StringIO適用於 Py2,但 Py3 給出:

rows = [[b'hello\xe6', b'world\xf8']]

    def rows_to_csv_data(rows):
        rows = [[col.encode('latin-1') for col in row] for row in rows]
        buf = StringIO()
        writer = csv.writer(buf)
>       writer.writerows(rows)
E       TypeError: a bytes-like object is required, not 'str'

這是我在這種情況下不明白的錯誤消息......

是否可以編寫一個適用於兩種 Python 的函數,或者我是否需要為 Py3 編寫一個完全獨立的函數?

這是通過測試的 Python 2 和 3 之間差異的說明。 在 Python 2.7 和 Python 3.6 上測試。

#!coding:utf8
import io
import csv
import sys

def rows_to_csv_data(rows):
    if sys.version_info.major == 2:
        rows = [[col.encode('latin1') for col in row] for row in rows]
        buf = io.BytesIO()
    else:
        buf = io.StringIO(newline='')

    writer = csv.writer(buf)
    writer.writerows(rows)

    if sys.version_info.major == 2:
        return buf.getvalue()
    else:
        return buf.getvalue().encode('latin1')

def test_rows_to_csv_data():
    rows = [[u'helloæ', u'worldø']]
    binary_data = rows_to_csv_data(rows)
    assert binary_data == u"helloæ,worldø\r\n".encode('latin-1')

test_rows_to_csv_data()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM