3 ответов:
вы могли бы использовать
pickleмодуль в стандартной библиотеке. Вот элементарное применение его к вашему примеру:import pickle class Company(object): def __init__(self, name, value): self.name = name self.value = value with open('company_data.pkl', 'wb') as output: company1 = Company('banana', 40) pickle.dump(company1, output, pickle.HIGHEST_PROTOCOL) company2 = Company('spam', 42) pickle.dump(company2, output, pickle.HIGHEST_PROTOCOL) del company1 del company2 with open('company_data.pkl', 'rb') as input: company1 = pickle.load(input) print(company1.name) # -> banana print(company1.value) # -> 40 company2 = pickle.load(input) print(company2.name) # -> spam print(company2.value) # -> 42вы также можете написать простую утилиту, такую как следующая, которая открывает файл и записывает в него один объект:
def save_object(obj, filename): with open(filename, 'wb') as output: # Overwrites any existing file. pickle.dump(obj, output, pickle.HIGHEST_PROTOCOL) # sample usage save_object(company1, 'company1.pkl')обновление:
поскольку это такой популярный ответ, я хотел бы коснуться нескольких слегка продвинутых тем использования.
cPickle(или_pickle) vspickleэто почти всегда предпочтительнее на самом деле использовать
cPickleмодуль, а неpickleпотому что первый написан на C и намного быстрее. Есть некоторые тонкие различия между ними, но в большинстве случаев они эквивалентны и версия C обеспечит очень высокую производительность. Переключение на него не может быть проще, просто изменитеimportзаявление на это:import cPickle as pickleВ Python 3,
cPickleбыла переименована в_pickle, но это уже не необходимо, так какpickleмодуль, теперь делает это автоматически-см. какая разница между pickle и _pickle в python 3?.краткое изложение вы могли бы использовать что-то вроде следующего, чтобы убедиться, что ваш код будет всегда используйте версию C, когда она доступна как в Python 2, так и в 3:
try: import cPickle as pickle except ModuleNotFoundError: import pickleформаты потока данных (протоколы)
pickleсмогите прочитать и написать файлы в нескольких различных, Специфичные для Python форматы, называемые протоколы. "Версия протокола 0 "-это ASCII и, следовательно,"читаемый человеком". Версии > 1 являются двоичными, и самый высокий из них зависит от того, какая версия Python используется. Значение по умолчанию зависит от версии Python. В Python 2 по умолчанию была версия протокола0, но в Python 3.6, это версия протокола3. В Python 3.x модуль имелpickle.DEFAULT_PROTOCOLдобавлено к нему, но это не существует в Python 2.к счастью, есть стенография для написания
pickle.HIGHEST_PROTOCOLв каждом вызове (предполагая, что это то, что вы хотите, и вы обычно делаете)-просто используйте буквенное число-1. Итак, вместо того, чтобы писать:pickle.dump(obj, output, pickle.HIGHEST_PROTOCOL)вы можете просто написать:
pickle.dump(obj, output, -1)в любом случае, вы бы только указать протокол один раз, если вы создали
Picklerобъект для использования в нескольких операциях рассол:pickler = pickle.Pickler(output, -1) pickler.dump(obj1) pickler.dump(obj2) etc...Несколько Объектов
в то время как файл рассола можете содержат любое количество маринованных объектов, как показано в приведенных выше примерах, когда их неизвестное количество, часто проще хранить их все в каком-то контейнере переменного размера, например
list,tupleилиdictи записать их все в файл одним вызовом:tech_companies = [ Company('Apple', 114.18), Company('Google', 908.60), Company('Microsoft', 69.18) ] save_object(tech_companies, 'tech_companies.pkl')и восстановить список и все в этом позже с:
with open('tech_companies.pkl', 'rb') as input: tech_companies = pickle.load(input)главное преимущество заключается в том, что вам не нужно знать, сколько экземпляров объектов сохраняются чтобы загрузить их позже (хотя делать это без этой информации и возможно, для этого требуется немного специализированный код). Смотрите ответы на соответствующий вопрос сохранение и загрузка нескольких объектов в файл огурчик? подробнее о различных способах сделать это. Лично я как @Lutz Prechelt's ответ лучшие. Вот он адаптирован к примерам здесь:
class Company: def __init__(self, name, value): self.name = name self.value = value def pickled_items(filename): """ Unpickle a file of pickled data. """ with open(filename, "rb") as f: while True: try: yield pickle.load(f) except EOFError: break print('Companies in pickle file:') for company in pickled_items('company_data.pkl'): print(' name: {}, value: {}'.format(company.name, company.value))
я думаю, что это довольно сильное предположение, чтобы предположить, что объект является
class. Что, если это неclass? Есть также предположение, что объект не был определен в переводчик. Что делать, если он был определен в интерпретаторе? Кроме того, что делать, если атрибуты были добавлены динамически? Когда некоторые объекты Python имеют атрибуты, добавленные к их__dict__после создания,pickleне уважает добавление этих атрибутов (т. е. он "забывает", что они были добавлены - потому чтоpickleсериализует по ссылке на определение объекта).во всех этих случаях
pickleиcPickleможет подвести вас ужасно.если вы хотите сохранить
object(произвольно созданный), где у вас есть атрибуты (либо добавленные в определение объекта, либо позже)... лучше всего использоватьdill, который может сериализовать почти все в python.начнем с класса...
Python 2.7.8 (default, Jul 13 2014, 02:29:54) [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. >>> import pickle >>> class Company: ... pass ... >>> company1 = Company() >>> company1.name = 'banana' >>> company1.value = 40 >>> with open('company.pkl', 'wb') as f: ... pickle.dump(company1, f, pickle.HIGHEST_PROTOCOL) ... >>>теперь закрыли, и перезапуск...
Python 2.7.8 (default, Jul 13 2014, 02:29:54) [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. >>> import pickle >>> with open('company.pkl', 'rb') as f: ... company1 = pickle.load(f) ... Traceback (most recent call last): File "<stdin>", line 2, in <module> File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 1378, in load return Unpickler(file).load() File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 858, in load dispatch[key](self) File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 1090, in load_global klass = self.find_class(module, name) File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 1126, in find_class klass = getattr(mod, name) AttributeError: 'module' object has no attribute 'Company' >>>Упс...
pickleне могу с этим справиться. Давайте попробуемdill. Мы добавим другой тип объекта (alambda) для хорошей мерой.Python 2.7.8 (default, Jul 13 2014, 02:29:54) [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. >>> import dill >>> class Company: ... pass ... >>> company1 = Company() >>> company1.name = 'banana' >>> company1.value = 40 >>> >>> company2 = lambda x:x >>> company2.name = 'rhubarb' >>> company2.value = 42 >>> >>> with open('company_dill.pkl', 'wb') as f: ... dill.dump(company1, f) ... dill.dump(company2, f) ... >>>а теперь прочтите файл.
Python 2.7.8 (default, Jul 13 2014, 02:29:54) [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. >>> import dill >>> with open('company_dill.pkl', 'rb') as f: ... company1 = dill.load(f) ... company2 = dill.load(f) ... >>> company1 <__main__.Company instance at 0x107909128> >>> company1.name 'banana' >>> company1.value 40 >>> company2.name 'rhubarb' >>> company2.value 42 >>>это работает. Причина
pickleне иdillне, этоdillотносится к__main__как модуль (по большей части), а также может мариновать определения классов вместо маринования по ссылке (напримерpickleделает). Причинаdillможно солить аlambdaэто то, что он дает ему имя... тогда маринование магии может произойти.на самом деле, есть более простой способ сохранить все эти объекты, особенно если у вас есть много объектов, которые вы создали. Просто сбросьте всю сессию python и вернитесь к ней позже.
Python 2.7.8 (default, Jul 13 2014, 02:29:54) [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. >>> import dill >>> class Company: ... pass ... >>> company1 = Company() >>> company1.name = 'banana' >>> company1.value = 40 >>> >>> company2 = lambda x:x >>> company2.name = 'rhubarb' >>> company2.value = 42 >>> >>> dill.dump_session('dill.pkl') >>>теперь выключите компьютер, идите наслаждаться эспрессо или что-то еще, и вернуться позже...
Python 2.7.8 (default, Jul 13 2014, 02:29:54) [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. >>> import dill >>> dill.load_session('dill.pkl') >>> company1.name 'banana' >>> company1.value 40 >>> company2.name 'rhubarb' >>> company2.value 42 >>> company2 <function <lambda> at 0x1065f2938>единственным серьезным недостатком является то, что
dillне является частью стандарта python библиотека. Поэтому, если вы не можете установить пакет python на своем сервере, вы не можете его использовать.однако, если вы можете установить пакеты python в своей системе, вы можете получить последнюю версию
dillСgit+https://github.com/uqfoundation/dill.git@master#egg=dill. И вы можете получить последнюю выпущенную версию сpip install dill.
можно использовать anycache чтобы сделать работу за вас. Он рассматривает все детали:
- он использует укроп в качестве бэкэнда, который расширяет python
pickleмодуль для обработкиlambdaи все хорошо особенности python.- он хранит разные объекты в разных файлах и перезагружает их правильно.
- ограничивает размер кэша
- позволяет очистить кэш
- позволяет совместное использование объектов между несколькими работает
- позволяет уважать входные файлы, которые влияют на результат
если у вас есть функция
myfuncкоторый создает экземпляр:from anycache import anycache class Company(object): def __init__(self, name, value): self.name = name self.value = value @anycache(cachedir='/path/to/your/cache') def myfunc(name, value) return Company(name, value)Anycache вызывает
myfuncв первый раз и соленья результат файл вcachedirС помощью уникального идентификатора (в зависимости от имени функции и ее аргументов) в качестве имени файла. При любом последовательном запуске загружается маринованный объект. Еслиcachedirсохраняется между запусками python, маринованный объект берется из предыдущего запуска python.для получения дополнительной информации см. документация
Comments