在迁移到Python 3时,我注意到我们使用内置csv
生成的一些文件现在每个字符串周围都有b'
前缀...
这里的代码应根据dogs
定义的一些参数生成export_fields
列表的.csv(因此始终返回unicode数据):
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
])
问题是,一旦我返回file_content.getvalue()
,我得到:
b'Does he bark?' b'Full Name' b'Gender'
b'Sometimes, yes' b'Woofy the dog' b'Male'
而不是 (缩进已被修改为在SO上可读) :
'Does he bark?' 'Full Name' 'Gender'
'Sometimes, yes' 'Woofy the dog' 'Male'
我在encoding
模块中找不到任何csv
参数。我希望整个文件在cp1252中编码,所以我并不关心编码是通过行的迭代还是在构建的文件上完成的。
那么,有没有人知道如何生成一个合适的字符串,只包含cp1252编码的字符串?
答案 0 :(得分:1)
csv
模块处理文本,并使用str()
将非字符串的任何内容转换为字符串。
不要传递bytes
个对象。传递str
对象或类型,使用str()
干净地转换为字符串。这意味着你不应该编码字符串。
如果您需要输出cp1252
,请对StringIO
值进行编码:
file_content.getvalue().encode('cp1252')
因为StringIO
个对象也只处理文本。
更好的是,当csv
模块写入文件对象时,使用BytesIO
object和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'