Usando pickle.dump - TypeError: deve ser str, não bytes

242

Estou usando python3.3 e estou tendo um erro enigmático ao tentar selecionar um dicionário simples.

Aqui está o código:

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)

e eu recebo:

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
John Rowland
fonte

Respostas:

404

O arquivo de saída precisa ser aberto no modo binário:

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

precisa ser:

f = open('varstor.txt','wb')
Jon Clements
fonte
22
Depois de encontrar exatamente o mesmo problema, vi onde a necessidade de leitura / gravação "binária" foi mencionada nos documentos para pickle.dump()e pickle.load(). Nos dois lugares, isso foi mencionado apenas de passagem no meio da explicação da função. Alguém deve deixar isso mais claro.
28514 Matthew Matthew
9
Eu arquivei # 24159 com o projeto Python. Talvez haja algo que possa ser feito para melhorar a experiência nesta e em situações semelhantes.
Jason R. Coombs
1
Este artigo não menciona usando o modo WB e aparece no topo dos resultados da pesquisa e foi escrito em 2019: thoughtco.com/using-pickle-to-save-objects-2813661
deltaray
22

Só tive o mesmo problema. No Python 3, os modos binários 'wb', 'rb' devem ser especificados, enquanto no Python 2x, eles não são necessários. Quando você segue tutoriais baseados em Python 2x, é por isso que você está aqui.

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
fonte