Подтвердить что ты не робот

Сохранение и загрузка объектов и использование рассола

Я пытаюсь сохранить и загрузить объекты с помощью модуля pickle.
Сначала объявляю свои объекты:

>>> class Fruits:pass
...
>>> banana = Fruits()

>>> banana.color = 'yellow'
>>> banana.value = 30

После этого я открываю файл под названием "Fruits.obj" (ранее я создал новый .txt файл и переименовал "Fruits.obj" ):

>>> import pickle
>>> filehandler = open(b"Fruits.obj","wb")
>>> pickle.dump(banana,filehandler)

После этого я закрою сеанс, и я начал новый, и я поставил следующий (попытка доступа к объекту, который он должен был сохранить):

file = open("Fruits.obj",'r')
object_file = pickle.load(file)

Но у меня есть это сообщение:

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python31\lib\pickle.py", line 1365, in load
encoding=encoding, errors=errors).load()
ValueError: read() from the underlying stream did notreturn bytes

Я не знаю, что делать, потому что я не понимаю этого сообщения. Кто-нибудь знает, как я могу загрузить свой объект "банан"? Спасибо!

EDIT: Как я уже сказал, я сказал:

>>> import pickle
>>> file = open("Fruits.obj",'rb')

Не было проблем, но следующий вопрос:

>>> object_file = pickle.load(file)

И у меня есть ошибка:

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python31\lib\pickle.py", line 1365, in load
encoding=encoding, errors=errors).load()
EOFError
4b9b3361

Ответ 1

Что касается второй проблемы:

 Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
 File "C:\Python31\lib\pickle.py", line
 1365, in load encoding=encoding,
 errors=errors).load() EOFError

После того, как вы прочтете содержимое файла, указатель файла будет в конце файла - дальнейших данных для чтения не будет. Вы должны перемотать файл так, чтобы он был снова прочитан:

file.seek(0)

Что вы обычно хотите сделать, это использовать диспетчер контекста, чтобы открыть файл и прочитать данные из него. Таким образом, файл будет автоматически закрыт после завершения выполнения блока, что также поможет организовать операции с файлами в значимые фрагменты.

Наконец, cPickle является более быстрой реализацией модуля рассола в C. Итак:

In [1]: import cPickle

In [2]: d = {"a": 1, "b": 2}

In [4]: with open(r"someobject.pickle", "wb") as output_file:
   ...:     cPickle.dump(d, output_file)
   ...:

# pickle_file will be closed at this point, preventing your from accessing it any further

In [5]: with open(r"someobject.pickle", "rb") as input_file:
   ...:     e = cPickle.load(input_file)
   ...:

In [7]: print e
------> print(e)
{'a': 1, 'b': 2}

Ответ 2

Для меня работает следующее:

class Fruits: pass

banana = Fruits()

banana.color = 'yellow'
banana.value = 30

import pickle

filehandler = open("Fruits.obj","wb")
pickle.dump(banana,filehandler)
filehandler.close()

file = open("Fruits.obj",'rb')
object_file = pickle.load(file)
file.close()

print(object_file.color, object_file.value, sep=', ')
# yellow, 30

Ответ 3

Всегда открывать в двоичном режиме, в этом случае

file = open("Fruits.obj",'rb')

Ответ 4

Вы тоже забыли прочитать его как двоичный файл.

В вашей части записи у вас есть:

open(b"Fruits.obj","wb") # Note the wb part (Write Binary)

В прочитанной части у вас есть:

file = open("Fruits.obj",'r') # Note the r part, there should be a b too

Поэтому замените его на:

file = open("Fruits.obj",'rb')

И он будет работать:)


Что касается вашей второй ошибки, это, скорее всего, причина, не закрывая/синхронизируя файл должным образом.

Попробуйте этот бит кода для записи:

>>> import pickle
>>> filehandler = open(b"Fruits.obj","wb")
>>> pickle.dump(banana,filehandler)
>>> filehandler.close()

И это (без изменений), чтобы читать:

>>> import pickle
>>> file = open("Fruits.obj",'rb')
>>> object_file = pickle.load(file)

Более простая версия будет использовать инструкцию with.

Для записи:

>>> import pickle
>>> with open('Fruits.obj', 'wb') as fp:
>>>     pickle.dump(banana, fp)

Для чтения:

>>> import pickle
>>> with open('Fruits.obj', 'rb') as fp:
>>>     banana = pickle.load(fp)

Ответ 5

Вы не открыли файл в двоичном режиме.

open("Fruits.obj",'rb')

Должен работать.

Для вашей второй ошибки файл, скорее всего, пустой, что означает, что вы случайно опорожнили его или использовали неправильное имя файла или что-то в этом роде.

(Предполагается, что вы действительно закрыли сеанс. Если нет, то это потому, что вы не закрыли файл между записью и чтением).

Я проверил ваш код, и он работает.

Ответ 6

Кажется, вы хотите сохранить экземпляры класса в сеансах, а использование pickle - достойный способ сделать это. Однако существует пакет под названием klepto, который абстрагирует сохранение объектов на интерфейс словаря, поэтому вы можете выбрать сортировку объектов и сохранить их в файле (как показано ниже) или рассортировать объекты и сохранять их в базе данных, или вместо использования pickle использовать json или многие другие варианты. Самое приятное в klepto заключается в том, что, абстрагируясь с общим интерфейсом, это упрощает работу, поэтому вам не нужно запоминать детали низкого уровня, как сохранять с помощью травления в файл или иначе.

Обратите внимание, что он работает для динамически добавленных атрибутов класса, которые не могут выполнить сортировку...

[email protected]>$ python
Python 2.7.6 (default, Nov 12 2013, 13:26:39) 
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from klepto.archives import file_archive 
>>> db = file_archive('fruits.txt')
>>> class Fruits: pass
... 
>>> banana = Fruits()
>>> banana.color = 'yellow'
>>> banana.value = 30
>>> 
>>> db['banana'] = banana 
>>> db.dump()
>>> 

Затем мы перезапускаем...

[email protected]>$ python
Python 2.7.6 (default, Nov 12 2013, 13:26:39) 
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from klepto.archives import file_archive
>>> db = file_archive('fruits.txt')
>>> db.load()
>>> 
>>> db['banana'].color
'yellow'
>>> 

klepto работает на python2 и python3.

Получить код здесь: https://github.com/uqfoundation

Ответ 7

Вы можете использовать anycache, чтобы выполнить эту работу за вас. Предполагая, что у вас есть функция myfunc, которая создает экземпляр:

from anycache import anycache

class Fruits:pass

@anycache(cachedir='/path/to/your/cache')    
def myfunc()
    banana = Fruits()
    banana.color = 'yellow'
    banana.value = 30
return banana

Anycache вызывает myfunc в первый раз и рассотает результат на файл в cachedir с использованием уникального идентификатора (в зависимости от имени функции и аргументов) в качестве имени файла. При любом последовательном прогоне загружается маринованный объект.

Если cachedir сохраняется между прогонами python, маринованный объект берется из предыдущего запуска python.

Также учитываются аргументы функции. Реализованная реализация также работает:

from anycache import anycache

class Fruits:pass

@anycache(cachedir='/path/to/your/cache')    
def myfunc(color, value)
    fruit = Fruits()
    fruit.color = color
    fruit.value = value
return fruit