在Python中将字符串写入文件

13

我在尝试将一个字符串写入Python文件时遇到了以下错误:

Traceback (most recent call last):
  File "export_off.py", line 264, in execute
    save_off(self.properties.path, context)
  File "export_off.py", line 244, in save_off
    primary.write(file)
  File "export_off.py", line 181, in write
    variable.write(file)
  File "export_off.py", line 118, in write
    file.write(self.value)
TypeError: must be bytes or buffer, not str

我基本上有一个字符串类,其中包含一个字符串:

class _off_str(object):
    __slots__ = 'value'
    def __init__(self, val=""):
        self.value=val

    def get_size(self):
        return SZ_SHORT

    def write(self,file):
        file.write(self.value)

    def __str__(self):
        return str(self.value)
此外,我是这样调用该类的(其中变量是一个 _off_str 对象数组):
def write(self, file):
    for variable in self.variables:
        variable.write(file)

我不知道发生了什么。我已经看到其他Python程序将字符串写入文件,那么为什么这个程序不能呢?

非常感谢您的帮助。

编辑:看起来我需要说明如何打开文件,以下是我的做法:

file = open(filename, 'wb')
primary.write(file)
file.close()

3
我回答了你的问题,但我也有一个问题。既然Python本身有几个非常强大的内置类,为什么你要在Python中编写自己的字符串类? - Bite code
1
或者更强烈地说,不要发明自己的字符串类。这种做法会导致软件难以维护。 - S.Lott
1
我并不想这样做,只是因为包中的其他文件也是这样做的。最终,我同意了你的看法,认为这样做真的很愚蠢,于是就将其删除了。我们再看看是否会有人抱怨。 - Leif Andersen
“包中的其他文件?” 你是说每个模块都发明了自己的字符串类吗?你正在使用什么? - S.Lott
Blender中的导出脚本。不过可能只是因为我没有理解它们。如果你很在意的话,我特别看了一下export_3ds。 - Leif Andersen
5个回答

25

你使用的是哪个版本的Python?在Python 3.x中,字符串包含了无特定编码的Unicode文本。要将其写入字节流(文件)中,必须将其转换为字节编码,如UTF-8、UTF-16等。幸运的是,这可以通过encode()方法轻松完成:

Python 3.1.1 (...)
>>> s = 'This is a Unicode string'
>>> print(s.encode('utf-8'))

另一个例子,将UTF-16写入文件:

>>> f = open('output.txt', 'wb')
>>> f.write(s.encode('utf-16'))

最后,你可以使用Python 3的“自动魔法”文本模式,它将自动将你的str转换为你指定的编码:

>>> f = open('output.txt', 'wt', encoding='utf-8')
>>> f.write(s)

我正在使用Python 3.x系列。谢谢,我现在会尝试编码。 - Leif Andersen
@Nate,如果你只是打开文件f = open('output.txt', 'w')会发生什么?Python 3会使用什么编码? - foglerit
2
@jonnat 当你这样做时,你会得到一个TextIOWrapper,它使用你的首选编码,由调用locale.getpreferredencoding(False)确定,这可能是UTF-8。我总是会指定编码,或者如果我想写入没有编码的bytes,则使用'wb' - Nate

9
我猜测您正在使用Python 3,并以二进制模式打开文件,这将只接受字节或缓冲区写入其中。
有没有可能让我们看到打开文件进行写入的代码?
编辑:看起来这确实是罪魁祸首。

2
我看不到你先打开文件:
file_handler = open(path)
file_handler.write(string)
file_handler.close()

嗯...那实际上在我的代码的另一个部分。我调用了写入方法(最后一个,带有这个):file = open(filename, 'wb') primary.write(file) file.close()但是你说得很好。 - Leif Andersen
@Leif Andersen:如果您没有发布足够的代码让我们看到并复现问题,那么您将无法得到很好的答案。 - S.Lott
@S.Lott,抱歉,我只是觉得这不重要,而且会让问题变得混乱,现在已经加上了。 - Leif Andersen
1
@Leif Andersen:足以重现问题的足够代码永远不可能被称为“混乱”。 - S.Lott

1

我在你的评论中看到你提到了你做过

file = open('xxx.xxx' ,'wb')

这意味着您正在以二进制模式打开文件进行写入(因此只需省略b标志)。


如果你仔细观察,variable.write(file) 实际上调用了 file.write(variable) - Mike Boers
通过反过来做,我在变量[i]对象上调用了write方法。我知道这是无意义的,但由于其他文件使用了这种风格,所以我应该坚持使用它。此外,在_str_off类中,代码确实有:def write(self,file): file.write(self.value)这确实会执行:file.write(variable) - Leif Andersen
@Mike Boers,已更新我的帖子。@Leif Andersen:已更新我的帖子。 - ChristopheD
实际上,文件的早期版本(为Python 2.5编写)使用了字符串。我会试一下。 - Leif Andersen

0
你是怎么打开这个文件的?
根据错误信息,我猜测:
f = open("file", "wb") # b for binary mode

如果你想使用字符串,你必须使用:

f = open("file", "w") 

如果你使用 "b",文件会期望二进制数据,而你正在写入一个字符串的 self.value
顺便说一句,不要使用 file 作为变量名,因为它会隐藏 Python 内置对象 file

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接