如何以二进制模式编写csv文件?

2022-01-09 00:00:00 python csv binary

问题描述

python 的 csv writer 不再支持二进制模式了吗?

Does python's csv writer not support binary mode anymore?

直到现在我才不得不在 'b' 模式下写入,但我遇到了非常烦人的错误,如下所示:

I haven't had to write in 'b' mode until now and i'm getting very annoying errors like so:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-2-030fb0c9dc9a> in <module>()
  4 with open('test.csv', 'wb') as f:
  5     w = csv.writer(f)
----> 6     w.writerows(rows)

TypeError: a bytes-like object is required, not 'str'

代码:

import csv

rows = [b'1,2,3', b'4,5,6', b'7,8,9']
with open('test.csv', 'wb') as f:
    w = csv.writer(f)
    w.writerows(rows)

如果有人能解释错误,那就太好了.我传入了一个迭代,其中每个元素都是一个字节序列,但我仍然收到一个错误,即输入不是字节"而是str".这种行为似乎出乎意料.

If anyone could explain the error that would be great. I'm passing in an iterable where every element is a byte sequence but I still get an error about the input not being 'bytes' but instead being 'str.' This behavior seems unexpected.

我知道如果我关闭二进制模式,上面的代码片段可以写入普通文件.如果有人有建设性的解决方案或建议,我将非常感激.

I know the above code snippet can write to a normal file if I turn off the binary mode. If anyone has a solution or suggestion that is constructive I would very much appreciate it.


解决方案

Python 3 中的 csv 模块总是尝试写入字符串,而不是字节:

The csv module in Python 3 always attempts to write strings, not bytes:

为了尽可能轻松地与实现 DB API 的模块进行交互,值 None 被写为空字符串.[...] 所有其他非字符串数据在写入之前都使用 str() 进行字符串化.

To make it as easy as possible to interface with modules which implement the DB API, the value None is written as the empty string. [...] All other non-string data are stringified with str() before being written.

这意味着你必须向它传递一个接受字符串的文件对象,这通常意味着以文本模式打开它.

That means you have to pass it a file object that accepts strings, which usually means opening it in text mode.

如果您遇到需要字节的文件对象,请将其包装在 io.TextIOWrapper 处理 str->bytes 编码:

If you are stuck with a file object that wants bytes, wrap it in an io.TextIOWrapper to handle str->bytes encoding:

# assuming you want utf-8
with io.TextIOWrapper(binary_file, encoding='utf-8', newline='') as text_file:
    w = csv.writer(text_file)

相关文章