CSV 模块的编写器不允许我写出二进制文件

发布于 2024-10-25 05:37:59 字数 786 浏览 1 评论 0原文

我尝试在打开文件时仅使用“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)

我认为它可以工作,但它仍然给我以下错误: “类型错误:必须是字节或缓冲区,而不是 str” 在“dataWriter.writerow(rowData)”行上。

任何帮助将不胜感激。 谢谢。

I tried to just use the 'w' tag while opening the file, but it double spaced the lines which caused the read to not work. So I found that changing to 'wb' will be the correct formatting. Now that I am using the 'wb' flag I can't get the csv.writer.writerow() to work. I have encoded all my strings and am lost as to why I keep getting this error. All the questions I see say that b'string here' or myString.encode('ascii') solves the error I get, but it is not solving it for me. Here is what I have:

    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)

Which I figured would work but it still gives me the following error:
"TypeError: must be bytes or buffer, not str"
on the line "dataWriter.writerow(rowData).

Any help would be apreciated.
Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

如何视而不见 2024-11-01 05:38:00

您似乎正在运行 Python 3.x。 关于对 csv 文件使用二进制模式的建议适用于 Python 2.x。3.x 不需要编解码器模块 - 只需在打开时使用 encoding=whatever文件。 3.x 需要的是使用 newline='' 打开文件。这适用于阅读和写作,尽管没有书面记录(错误报告已提交)。解决双倍间距问题后,这将起作用:

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)

You appear to be running Python 3.x. Advice about using binary mode for csv files applies to Python 2.x. The codecs module is not required for 3.x -- just use encoding=whatever when you open the file. What is needed for 3.x is that the file be opened with newline=''. This applies to both reading and writing, although it is not documented for writing (bug report has been submitted). After sorting out your doble-spacing problem, this will work:

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)

Contents of output file:

>>> open('demo.csv', 'rb').read()
b'\xc3\xbforick,123.456\r\npolonius,987.564\r\n'
>>>

Suggestion: give some consideration to legibility of your code ... instead of

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)

try

table = self.ui.table
for i in range(table.rowCount()):
    row = [table.item(i, j).text() for j in range(5)]
    writer.writerow(row)
赏烟花じ飞满天 2024-11-01 05:38:00

在 Python 3 中,在二进制模式下使用 open 会创建一个 io.BufferedWriter,它需要字节,而不是字符串。通过使用 encode 方法,您可以将字符串转换为字节;但我认为 cvs.writer.writerow 在写入之前将这些字节转换回字符串。

您应该尝试找出导致双倍行距的原因,而不是以二进制模式打开文件。我有两个问题:

  1. 您使用什么平台?

  2. print repr(self.ui.table.item(i,4).text()) 的输出是什么?

我的猜测是,brandizzi 的 strip() 方法可以工作,但如果不行,我们需要进行一些故障排除。

编辑:好的,John Machin 的帖子澄清了一切。在 Python 3 中解决此问题的正确方法是使用 newline='' 打开文件,这会禁用自动换行符翻译。 此错误报告包含一些有用的信息。

In Python 3, using open in binary mode creates an io.BufferedWriter, which wants bytes, not strings. By using the encode method, you change your strings into bytes; but I think cvs.writer.writerow converts those bytes back into strings before writing.

Instead of opening the file in binary mode, you should try to figure out what's causing the double spacing. I have two questions:

  1. What platform are you using?

  2. What is the output of print repr(self.ui.table.item(i,4).text())?

My guess is that brandizzi's strip() method will work, but if not, we'll need to do some troubleshooting.

Edit: Ok, John Machin's post clears it all up. The correct way to fix this problem in Python 3 is to open the file with newline='', which disables automatic newline translation. This bug report contains some helpful information.

墨洒年华 2024-11-01 05:38:00

也许您可以让 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'])

Maybe you could let the codecs module do the Unicode encoding for you, and try something like this instead:

import codecs, csv

with codecs.open(fileName, 'w', encoding = 'utf_8') as f:
    writer = csv.writer(f)
    writer.writerow(['some string', 'some other string'])
我乃一代侩神 2024-11-01 05:38:00

我在尝试将 csv 写入 paramiko sftp 文件流时遇到了这个问题,该文件无法在文本模式下打开。

我想出的也适用于OP的解决方案是:

import codecs, csv, io
buf = io.BytesIO()
StreamWriter = codecs.getwriter( 'utf-8' )
w = csv.writer( StreamWriter( buf ))
w.writerow([ 'foo', 'bar' ])
w.writerow([ 'bar', 'foo' ])
print( repr( buf.getvalue() ))

产生正确的输出:

b'foo,bar\r\nbar,foo\r\n'

I'm running into this problem trying to write a csv to a paramiko sftp file stream which can't be opened in text mode.

The solution I came up with which would have worked for the OP as well was this:

import codecs, csv, io
buf = io.BytesIO()
StreamWriter = codecs.getwriter( 'utf-8' )
w = csv.writer( StreamWriter( buf ))
w.writerow([ 'foo', 'bar' ])
w.writerow([ 'bar', 'foo' ])
print( repr( buf.getvalue() ))

Produces correct output:

b'foo,bar\r\nbar,foo\r\n'
生生不灭 2024-11-01 05:38:00

我一点也不感到惊讶。如果您要写出一个值为 13 的字节,模块如何判断这是二进制字段的一部分,还是 CSV 中新记录的开始? CSV 文件不适合存储二进制数据。

如果你绝对需要它在那里,你可以研究 BASE 64 编码......

马丁

I'm hardly surprised. If you were to write out a byte of value 13, how is the module supposed to tell if this is part of a binary field, or the start of a new record in the CSV? CSV files are not suitable for storing binary data.

If you absolutely need it to be in there, you could look into BASE 64 encoding...

Martin

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文