使用 csv 模块编写非 Unicode
Write non-Unicode using csv module
在迁移到 Python 3 时,我注意到我们使用内置 csv
生成的一些文件现在每个字符串周围都有 b'
前缀...
这是代码,它应该根据 export_fields
定义的一些参数(因此总是 returns unicode 数据)为 dogs
的列表生成一个 .csv:
file_content = StringIO()
csv_writer = csv.writer(
file_content, delimiter='\t', quotechar='"', quoting=csv.QUOTE_MINIMAL
)
csv_writer.writerow([
header_name.encode('cp1252') for _v, header_name in export_fields
])
# Write content
for dog in dogs:
csv_writer.writerow([
get_value(dog).encode('cp1252') for get_value, _header in export_fields
])
问题是一旦我 returns file_content.getvalue()
,我得到:
b'Does he bark?' b'Full Name' b'Gender'
b'Sometimes, yes' b'Woofy the dog' b'Male'
而不是 (缩进已修改为可读):
'Does he bark?' 'Full Name' 'Gender'
'Sometimes, yes' 'Woofy the dog' 'Male'
我在 csv
模块中没有找到任何 encoding
参数。我希望整个文件在 cp1252 中编码,所以我真的不在乎编码是通过行的迭代完成的还是在文件本身构造上完成的。
那么,有谁知道如何生成仅包含 cp1252 编码字符串的正确字符串吗?
csv
模块处理 text,并使用 str()
将任何不是字符串的内容转换为字符串。
不要传入 bytes
个对象。传入 str
对象或类型,这些对象或类型可以使用 str()
干净地转换为字符串。这意味着你不应该编码字符串。
如果需要cp1252
输出,编码StringIO
值:
file_content.getvalue().encode('cp1252')
as StringIO
对象也只处理文本。
更好的是,当 csv
模块写入文件对象时,使用 BytesIO
object with a TextIOWrapper()
为您进行编码:
from io import BytesIO, TextIOWrapper
file_content = BytesIO()
wrapper = TextIOWrapper(file_content, encoding='cp1252', line_buffering=True)
csv_writer = csv.writer(
wrapper, delimiter='\t', quotechar='"', quoting=csv.QUOTE_MINIMAL)
# write rows
result = file_content.getvalue()
我在包装器上启用了行缓冲,这样每次写入一行时它都会自动刷新到 BytesIO
实例。
现在 file_content.getvalue()
生成字节串:
>>> from io import BytesIO, TextIOWrapper
>>> import csv
>>> file_content = BytesIO()
>>> wrapper = TextIOWrapper(file_content, encoding='cp1252', line_buffering=True)
>>> csv_writer = csv.writer(wrapper, delimiter='\t', quotechar='"', quoting=csv.QUOTE_MINIMAL)
>>> csv_writer.writerow(['Does he bark?', 'Full Name', 'Gender'])
36
>>> csv_writer.writerow(['Sometimes, yes', 'Woofy the dog', 'Male'])
35
>>> file_content.getvalue()
b'Does he bark?\tFull Name\tGender\r\nSometimes, yes\tWoofy the dog\tMale\r\n'
在迁移到 Python 3 时,我注意到我们使用内置 csv
生成的一些文件现在每个字符串周围都有 b'
前缀...
这是代码,它应该根据 export_fields
定义的一些参数(因此总是 returns unicode 数据)为 dogs
的列表生成一个 .csv:
file_content = StringIO()
csv_writer = csv.writer(
file_content, delimiter='\t', quotechar='"', quoting=csv.QUOTE_MINIMAL
)
csv_writer.writerow([
header_name.encode('cp1252') for _v, header_name in export_fields
])
# Write content
for dog in dogs:
csv_writer.writerow([
get_value(dog).encode('cp1252') for get_value, _header in export_fields
])
问题是一旦我 returns file_content.getvalue()
,我得到:
b'Does he bark?' b'Full Name' b'Gender'
b'Sometimes, yes' b'Woofy the dog' b'Male'
而不是 (缩进已修改为可读):
'Does he bark?' 'Full Name' 'Gender'
'Sometimes, yes' 'Woofy the dog' 'Male'
我在 csv
模块中没有找到任何 encoding
参数。我希望整个文件在 cp1252 中编码,所以我真的不在乎编码是通过行的迭代完成的还是在文件本身构造上完成的。
那么,有谁知道如何生成仅包含 cp1252 编码字符串的正确字符串吗?
csv
模块处理 text,并使用 str()
将任何不是字符串的内容转换为字符串。
不要传入 bytes
个对象。传入 str
对象或类型,这些对象或类型可以使用 str()
干净地转换为字符串。这意味着你不应该编码字符串。
如果需要cp1252
输出,编码StringIO
值:
file_content.getvalue().encode('cp1252')
as StringIO
对象也只处理文本。
更好的是,当 csv
模块写入文件对象时,使用 BytesIO
object with a TextIOWrapper()
为您进行编码:
from io import BytesIO, TextIOWrapper
file_content = BytesIO()
wrapper = TextIOWrapper(file_content, encoding='cp1252', line_buffering=True)
csv_writer = csv.writer(
wrapper, delimiter='\t', quotechar='"', quoting=csv.QUOTE_MINIMAL)
# write rows
result = file_content.getvalue()
我在包装器上启用了行缓冲,这样每次写入一行时它都会自动刷新到 BytesIO
实例。
现在 file_content.getvalue()
生成字节串:
>>> from io import BytesIO, TextIOWrapper
>>> import csv
>>> file_content = BytesIO()
>>> wrapper = TextIOWrapper(file_content, encoding='cp1252', line_buffering=True)
>>> csv_writer = csv.writer(wrapper, delimiter='\t', quotechar='"', quoting=csv.QUOTE_MINIMAL)
>>> csv_writer.writerow(['Does he bark?', 'Full Name', 'Gender'])
36
>>> csv_writer.writerow(['Sometimes, yes', 'Woofy the dog', 'Male'])
35
>>> file_content.getvalue()
b'Does he bark?\tFull Name\tGender\r\nSometimes, yes\tWoofy the dog\tMale\r\n'