对于个人项目,我正在尝试将 patterns 包升级到 Python 3。 实际上我正在运行 test:db.py,但我在 csv 类的 '__init__.py' 文件中遇到了以下错误:
这是 save() 函数的代码片段: 在那里,我们将 s 定义为 BytesIO() 流,因此要求函数将字节流式传输到 self csv 文件。 错误来自行:
w.writerows([[csv_header_encode(name, type) for name, type in self.fields]])
TypeError: a bytes-like object is required, not 'str' ( below, also the code for this function)
假设 csv_header_encode 可以传递字节,我检查了这一点,确实如此,但不知何故,在其转换为列表时,它更改为“str”。 如果我将 s 编码更改为 StringsIO 那么提示来自
f.write(BOM_UTF8)
任何帮助将不胜感激。
def save(self, path, separator=",", encoder=lambda v: v, headers=False, password=None, **kwargs):
""" Exports the table to a unicode text file at the given path.
Rows in the file are separated with a newline.
Columns in a row are separated with the given separator (by default, comma).
For data types other than string, int, float, bool or None, a custom string encoder can be given.
"""
# Optional parameters include all arguments for csv.writer(), see:
# http://docs.python.org/library/csv.html#csv.writer
kwargs.setdefault("delimiter", separator)
kwargs.setdefault("quoting", csvlib.QUOTE_ALL)
# csv.writer will handle str, int, float and bool:
s = BytesIO()
w = csvlib.writer(s, **kwargs)
if headers and self.fields is not None:
w.writerows([[csv_header_encode(name, type) for name, type in self.fields]])
w.writerows([[encode_utf8(encoder(v)) for v in row] for row in self])
s = s.getvalue()
s = s.strip()
s = re.sub("([^\"]|^)\"None\"", "\\1None", s)
s = (s if not password else encrypt_string(s, password)).encode('latin-1')
f = open(path, "wt")
f.write(BOM_UTF8)
f.write(s)
f.close()
def csv_header_encode(field, type=STRING):
# csv_header_encode("age", INTEGER) => "age (INTEGER)".
t = re.sub(r"^varchar\(.*?\)", "string", (type or ""))
t = t and " (%s)" % t or ""
return "%s%s" % (encode_utf8(field or ""), t.upper())
最佳答案
您可能尝试写入 BytesIO
对象,但 csv.writer()
仅处理字符串。来自 csv
writer objects documentation :
A row must be an iterable of strings or numbers
强调我的。 csv.writer()
还需要一个要写入的文本文件;该对象生成字符串:
[...] converting the user’s data into delimited strings on the given file-like object.
使用 io.StringIO
object相反,或者将 BytesIO 对象包装在 io.TextIOWrapper
object 中为您处理编码。无论哪种方式,您都需要将 Unicode 文本传递给 csv.writer()
。
因为您稍后再次将 s.getvalue()
数据视为字符串(使用定义为字符串的正则表达式,并使用 Latin-1 编码),您可能想写入文本文件(因此StringIO
)。
f.write(BOM_UTF8)
失败是一个单独的问题。 f
是以文本模式 ('wt'
) 打开的,因此需要字符串,而不是字节
。如果你想写
将文本写入开头带有 UTF-8 BOM 的 UTF-8 编码文件,您可以在打开文件时使用 utf-8-sig
编码:
open(path, 'w', encoding='utf-8-sig')
通常,您似乎以所有错误的方式混合字节和字符串。尽可能长时间地将文本保留为文本,并且仅在最后可能的时刻进行编码。此时此刻是在 path
位置写入文件时,您可以将编码完全留给文件对象。
关于python - csv 类编写器 : a bytes-like object is required, 不是 'str',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43413018/