340

I'm using python3.3 and I'm having a cryptic error when trying to pickle a simple dictionary.

Here is the code:

import os
import pickle
from pickle import *
os.chdir('c:/Python26/progfiles/')

def storvars(vdict):      
    f = open('varstor.txt','w')
    pickle.dump(vdict,f,)
    f.close()
    return

mydict = {'name':'john','gender':'male','age':'45'}
storvars(mydict)

and I get:

Traceback (most recent call last):
  File "C:/Python26/test18.py", line 31, in <module>
    storvars(mydict)
  File "C:/Python26/test18.py", line 14, in storvars
    pickle.dump(vdict,f,)
TypeError: must be str, not bytes
jb.
  • 23,300
  • 18
  • 98
  • 136
John Rowland
  • 3,579
  • 2
  • 15
  • 7

3 Answers3

555

The output file needs to be opened in binary mode:

f = open('varstor.txt','w')

needs to be:

f = open('varstor.txt','wb')
Jon Clements
  • 138,671
  • 33
  • 247
  • 280
  • 29
    *After* running into exactly the same problem, I saw where the need for "binary" reading/writing was mentioned in the [docs](https://docs.python.org/3/library/pickle.html#pickle.dump) for `pickle.dump()` and `pickle.load()`. Both places, this was mentioned only in passing near the middle of the function explanation. Someone should make this clearer. – Matthew Dec 28 '14 at 02:44
  • 11
    I filed [#24159](http://bugs.python.org/issue24159) with the Python project. Perhaps there is something that can be done to improve the experience in this and similar situations. – Jason R. Coombs May 10 '15 at 14:35
  • FWIW, the docs link in @Matthew's comment above does *not* mention the need for binary file in "near the middle of the function explanation". Perhaps they changed it since then? That being said, in hindsight we can search keyword "binary", and then it is mentioned in literally the first paragraph/sentence at the very top of [that doc page](https://docs.python.org/3.8/library/pickle.html). – RayLuo Jan 25 '21 at 05:39
  • this wasn't needed in python 2, for what it's worth. came across the same error converting my code from 2 to 3. – abcd Sep 01 '22 at 13:01
43

Just had same issue. In Python 3, Binary modes 'wb', 'rb' must be specified whereas in Python 2x, they are not needed. When you follow tutorials that are based on Python 2x, that's why you are here.

import pickle

class MyUser(object):
    def __init__(self,name):
        self.name = name

user = MyUser('Peter')

print("Before serialization: ")
print(user.name)
print("------------")
serialized = pickle.dumps(user)
filename = 'serialized.native'

with open(filename,'wb') as file_object:
    file_object.write(serialized)

with open(filename,'rb') as file_object:
    raw_data = file_object.read()

deserialized = pickle.loads(raw_data)


print("Loading from serialized file: ")
user2 = deserialized
print(user2.name)
print("------------")
Well Smith
  • 733
  • 7
  • 10
1

pickle uses a binary protocol, hence only accepts binary files. As the document said in the first sentence, "The pickle module implements binary protocols for serializing and de-serializing".

Xinzhe Li
  • 124
  • 4