【问题标题】:How to write UTF-8 CSV into BytesIO in Python3?如何在 Python3 中将 UTF-8 CSV 写入 BytesIO?
【发布时间】:2019-11-27 22:35:45
【问题描述】:

首先,我了解如何在 Python3 中从字符串编写 UTF-8,并且建议将 StringIO 用于此类字符串构建。但是,我特别需要一个 binary 类文件对象,为此我需要BytesIO。如果我执行以下操作,那么数据最终会爆炸,因为它被读取为 Latin1,我的计算机的默认语言环境/字符集。

with io.StringIO() as sb:
    csv.writer(sb).writerows(rows)
    sb.flush()
    sb.seek(0)
    # blows up with Latin1 encoding error
    job = bq.load_table_from_file(sb, table_ref, job_config=job_config)

所以我的解决方法是这个怪物使使用的内存量翻倍:

with io.StringIO() as sb:
    csv.writer(sb).writerows(rows)
    sb.flush()
    sb.seek(0)
    with io.BytesIO(sb.getvalue().encode('utf-8')) as buffer:
        job = bq.load_table_from_file(buffer, table_ref, job_config=job_config)

在这个链中的某处必须有一种方法来指定字节编码,这样sb 之类的文件的读者将看到数据为 UTF-8。或者有没有办法将csv.writer() 与字节流一起使用?

我已经在 StackOverflow 上查找了这两个答案,但我发现的通常是写入文件和内存中的内容,所有内容都指向 StringIO

【问题讨论】:

  • 必须有一种方法可以直接从rows 创建作业。否则,整个事情不仅在内存使用方面而且在 CPU 使用方面效率低下,因为以字节为单位编码字符并再次返回非常昂贵。
  • 嗯,创建作业需要联系 API 服务,这意味着必须将 rows 序列化为 JSON 或 CSV 等传输格式。

标签: python-3.x stringio


【解决方案1】:

有一个TextIOWrapper 类可以完成这项工作,但如果您使用上下文管理器with,它会关闭流并使原始BytesIO 对象无法使用。

修改我原来的例子:

with io.BytesIO() as buffer:
    sb = io.TextIOWrapper(buffer, 'utf-8', newline='')
    csv.writer(sb).writerows(rows)
    sb.flush()
    buffer.seek(0)
    job = bq.load_table_from_file(buffer, table_ref, job_config=job_config)

另一个警告是newline 参数,如果不考虑它,它会转换换行符。设置newline = '' 以防止这种情况发生。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-01
    • 2015-02-13
    • 2016-04-28
    • 2014-02-03
    • 1970-01-01
    • 2013-06-13
    相关资源
    最近更新 更多