python - 如何在 Py2 和 Py3 上将带有 unicode 数据的行转换为 latin-1 编码的 csv 数据?

标签 python python-3.x python-2.7

我想将包含 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'

我找不到任何方便的方法来使用 future 或六个库来做到这一点。

使用 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()

关于python - 如何在 Py2 和 Py3 上将带有 unicode 数据的行转换为 latin-1 编码的 csv 数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55434930/

相关文章:

python - 如何将 iPython HTML 类发送到 .html 文件?

python - 格式化固定宽度的字符串(unicode 和 utf8)

python - 为什么 itertools.count() 在与 zip 一起使用时会消耗额外的元素?

python - 覆盖数据框值

python - 从 .ui 自动完成

python - python中限制输入字符串的长度

python-2.7 - PyQt 4 : Get Position of Toolbar

python - django python - 关系不存在

python - Pygame:玩家 Sprite 与墙壁碰撞时动画不正确

python - Pandas :计算每组行内的正弦距离