CSV模块的写入器不允许我写入二进制数据
我尝试在打开文件时只用'w'这个标记,但这样会导致行之间出现双倍行距,导致读取时出错。所以我发现把标记改成'wb'才是正确的格式。现在我使用'wb'标记后,发现csv.writer.writerow()这个功能无法正常工作。我已经把所有字符串都编码过了,但还是搞不清楚为什么会一直出现这个错误。我看到的所有问题都说用b'string here'或者myString.encode('ascii')可以解决我遇到的错误,但对我来说并没有用。以下是我的代码:
dataWriter = csv.writer(open(fileName, 'wb'))
for i in range(self.ui.table.rowCount()):
rowData = [self.ui.table.item(i,0).text().encode('utf-8')\
,self.ui.table.item(i,1).text().encode('utf-8')\
,self.ui.table.item(i,2).text().encode('utf-8')\
,self.ui.table.item(i,3).text().encode('utf-8')\
,self.ui.table.item(i,4).text().encode('utf-8')]
dataWriter.writerow(rowData)
我以为这样可以正常工作,但仍然出现了以下错误: "TypeError: must be bytes or buffer, not str" 在"dataWriter.writerow(rowData)"这一行。
希望能得到一些帮助。 谢谢。
5 个回答
也许你可以让 codecs
模块来帮你处理Unicode编码,试试下面这个方法:
import codecs, csv
with codecs.open(fileName, 'w', encoding = 'utf_8') as f:
writer = csv.writer(f)
writer.writerow(['some string', 'some other string'])
在Python 3中,使用open
以二进制模式打开文件会创建一个io.BufferedWriter
,它需要的是字节(bytes),而不是字符串(strings)。通过使用encode
方法,你可以把字符串转换成字节;但是我觉得cvs.writer.writerow
在写入之前会把这些字节再转换回字符串。
与其以二进制模式打开文件,不如先找找是什么原因导致了双倍空格。我有两个问题:
你使用的是什么平台?
执行
print repr(self.ui.table.item(i,4).text())
的输出是什么?
我猜测brandizzi的strip()
方法可能会有效,但如果不行,我们就需要进行一些故障排除。
编辑:好的,John Machin的帖子解释得很清楚。在Python 3中解决这个问题的正确方法是以newline=''
打开文件,这样可以禁用自动换行转换。这个bug报告包含了一些有用的信息。
你似乎在使用Python 3.x版本。关于使用二进制模式处理csv文件的建议是针对Python 2.x的。 在3.x版本中,不需要使用codecs模块——只需在打开文件时使用encoding=whatever
。对于3.x版本,打开文件时需要使用 newline=''
。这适用于读取和写入文件,虽然写入时没有详细说明(已经提交了bug报告)。解决了你的双重空格问题后,这样做就可以了:
import csv
data = [
['\xfforick', 123.456],
['polonius', 987.564],
]
with open('demo.csv', 'w', newline='', encoding='utf8') as f:
writer = csv.writer(f)
for row in data:
writer.writerow(row)
输出文件的内容:
>>> open('demo.csv', 'rb').read()
b'\xc3\xbforick,123.456\r\npolonius,987.564\r\n'
>>>
建议:考虑一下你代码的可读性……而不是
for i in range(self.ui.table.rowCount()):
rowData = [self.ui.table.item(i,0).text().encode('utf-8')\
,self.ui.table.item(i,1).text().encode('utf-8')\
,self.ui.table.item(i,2).text().encode('utf-8')\
,self.ui.table.item(i,3).text().encode('utf-8')\
,self.ui.table.item(i,4).text().encode('utf-8')]
dataWriter.writerow(rowData)
尝试
table = self.ui.table
for i in range(table.rowCount()):
row = [table.item(i, j).text() for j in range(5)]
writer.writerow(row)