13

I'm getting the following error when trying to write a string to a file in pythion:

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

I basically have a string class, which contains a string:

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)

Furthermore, I'm calling that class like this (where variable is an array of _off_str objects:

def write(self, file):
    for variable in self.variables:
        variable.write(file)

I have no idea what is going on. I've seen other python programs writing strings to files, so why can't this one?

Thank you very much for your help.

Edit: It looks like I needed to state how I opened the file, here is how:

file = open(filename, 'wb')
primary.write(file)
file.close()
5
  • 3
    I answered to your question but I have one myself. Why the hell do you want to write your own string class in Python, while Python itself got several really powerfull classes built-in ? Commented Mar 22, 2010 at 20:11
  • 1
    Or, to put it more strongly. Please do not invent your own string class. This kind of thing makes software unmaintainable. Commented Mar 22, 2010 at 21:00
  • 1
    I didn't want to, it was just the way the other files in the package did it. In the end, I agreed with you, and thought that it was really dumb, and just ripped it right out. We'll see if anyone complains. Commented Mar 22, 2010 at 21:33
  • "the other files in the package?" You mean every other module invented their own string class? What are you working with? Commented Mar 22, 2010 at 22:47
  • The export scripts in blender. It also might just be that I didn't understand them though. I was especially looking at the export_3ds one, if you care that much. Commented Mar 22, 2010 at 23:12

5 Answers 5

25

What version of Python are you using? In Python 3.x a string contains Unicode text in no particular encoding. To write it out to a stream of bytes (a file) you must convert it to a byte encoding such as UTF-8, UTF-16, and so on. Fortunately this is easily done with the encode() method:

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

Another example, writing UTF-16 to a file:

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

Finally, you can use Python 3's "automagic" text mode, which will automatically convert your str to the encoding you specify:

>>> f = open('output.txt', 'wt', encoding='utf-8')
>>> f.write(s)
Sign up to request clarification or add additional context in comments.

3 Comments

I am on the 3.x series of python. Thank you, I'll try encode now.
@Nate, what happens if you just open the file as f = open('output.txt', 'w')? What encoding will Python 3 use?
@jonnat When you do that, you are getting a TextIOWrapper, and it uses your preferred encoding as determined by calling locale.getpreferredencoding(False), which is probably UTF-8. I would always specify the encoding, or use 'wb' if I wanted to write bytes with no encoding.
10

I suspect you are using Python 3 and have opened the file in binary mode, which will only accept bytes or buffers to be written into it.

Any chance we could see the code that opens up the file for writing?


edit: Looks like that is indeed the culprit.

Comments

2

I'm not seeing you open the file first:

file_handler = open(path)
file_handler.write(string)
file_handler.close()

4 Comments

Um...that's actually in another part of my code. I call the write method (the last one, with this): file = open(filename, 'wb') primary.write(file) file.close() but good point though.
@Leif Andersen: If you don't post enough of the code for us to see and reproduce the problem, you won't get much of an answer.
@S.Lott, sorry, I just didn't think it was important, and that it would clutter up the question, it's there now.
@Leif Andersen: Enough code to reproduce the problem cannot ever be called "clutter".
1

I see in you comment you mentioned that you did

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

That means you're opening the file to write in binary (so just leave out the b flag).

4 Comments

If you look closer, variable.write(file) does call file.write(variable).
(sorry about the hard to read code, it looks like I can't put good formatting it in comments) By doing the other way around, I'm calling the write method on the variable[i] object. Nonsensicle, I know, but for some reason, that's the style that the other files used, so I should probably stick with it. Also, the code did have that, in the _str_off class, I had: def write(self,file): file.write(self.value) which did do a: file.write(variable)
@Mike Boers, True, updated my post. @Leif Andersen: updated my post.
Really, an earlier version of the file (written for python 2.5), used strings. I'll give it a shot.
0

How did you open the file ?

According to the error message, I'll guess :

f = open("file", "wb") # b for binary mode

If you want to use strings, you must use :

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

If you use "b", files will expect binary data, and you are writing self.value which is a string.

By the way, don't use file" as a variable name as it hides the file built-in Python object.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.