Вы можете использовать модуль 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
) против pickle
Почти всегда предпочтительнее использовать модуль 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.7 это версия протокола 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...
Примечание : Если вы работаете в среде, в которой работают разные версии Python, вам, вероятно, захочется явно (т. Е. Жестко закодировать) определенный номер протокола, который все они могут прочитать (более поздние версии) обычно может читать файлы, созданные ранее).
Несколько объектов
Несмотря на то, что файл маринованных файлов может содержать любое количество маринованных объектов, как показано в приведенных выше примерах, при их неизвестном количестве часто проще хранить их все в файлах различного размера. контейнер, например 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 answer лучший. Вот он адаптированный к примерам здесь:
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))