Как сохранить, а затем извлечь нативные структуры данных Python в файл и из него? - PullRequest
3 голосов
/ 28 августа 2010

Я читаю файл XML и реорганизую нужные данные в структуры данных Python (списки, кортежи и т. Д.)

Например, один из моих модулей анализатора XML создает следующие данные:

# data_miner.py
animals = ['Chicken', 'Sheep', 'Cattle', 'Horse']
population = [150, 200, 50, 30]

Затем у меня есть модуль плоттера, который примерно говорит, например:

# plotter.py
from data_miner import animals, population

plot(animals, population)

Используя этот метод, мне приходится анализировать XML-файл каждый раз, когда я строю график.Я все еще тестирую другие аспекты моей программы, и файл XML пока не меняется так часто.Отказ от этапа синтаксического анализа значительно улучшил бы мое время тестирования.

Это мой желаемый результат:
Между data_miner.py и plotter.py мне нужен файл, содержащий animals и population таким образом, что к ним можно получить доступ plotter.py изначально (например, без изменений в коде печати), без необходимости каждый раз запускать data_miner.py.Если это возможно, он не должен быть в csv или любом другом формате ASCII, просто в формате, доступном изначально.plotter.py теперь должен выглядеть примерно так:

# plotter.py

# This line may not necessarily be a one-liner.
from data_file import animals, population

# But I want this portion to stay the same
plot(animals, population)

Аналогия:
Это примерно эквивалентно команде save MATLAB, которая сохраняет переменные активного рабочего пространства в .matфайл.Я ищу что-то похожее на файл .mat для Python.

Недавний опыт:
Я видел pickle и cpickle, но я неуверен, как заставить его работать.Если это правильный инструмент для использования, пример кода будет очень полезен.Могут быть и другие инструменты, которые я пока не знаю.

Ответы [ 4 ]

5 голосов
/ 28 августа 2010

Модуль pickle, или его более быстрый эквивалент cPickle, должен хорошо служить вашим потребностям.

В частности:

# data_miner.py
import pickle

animals = ['Chicken', 'Sheep', 'Cattle', 'Horse']
population = [150, 200, 50, 30]

with open('data_miner.pik', 'wb') as f:
  pickle.dump([animals, population], f, -1)

и

# plotter.py
import pickle

with open('data_miner.pik', 'rb') as f:
    animals, population = pickle.load(f)

print animals, population

Здесь я сделал data_miner.py довольно явным в отношении того, что нужно сохранить (всегда отличная идея, чтобы быть очень явным, если у вас нет особых причин поступать иначе).Некоторые вещи (такие как модули и открытые файлы) не могут быть все равно извлечены, поэтому простое засечение globals() не сработает.

Если вам абсолютно необходимо, вы могли бы сделать копиюglobals() при удалении всех объектов, типы которых делают их неподходящими для сохранения;или, возможно, лучше, религиозно использовать начальный _ в каждом имени, которое вы не хотите сохранить (например, import pickle as _pickle, with open ... as _f и т. д.) и исключить из копии globals() все имена с начальным подчеркиванием == при таком подходе pickle.load будет извлекать dict, тогда интересующие переменные будут извлечены из него путем индексации.Тем не менее, я бы настоятельно рекомендовал простую альтернативу сохранения list (или dict, если хотите ;-) с конкретными значениями , которые на самом деле представляют интерес, вместо того, чтобы брать "оптовую продажу"подход.

2 голосов
/ 28 августа 2010

Засолка хороша, если у вас есть специфичные для Python объекты для сохранения.Если это просто общие данные в каком-то базовом типе контейнера, тогда JSON - это хорошо.

>>> json.dumps(['Chicken', 'Sheep', 'Cattle', 'Horse'])
'["Chicken", "Sheep", "Cattle", "Horse"]'
>>> json.dump(['Chicken', 'Sheep', 'Cattle', 'Horse'], sys.stdout) ; print
["Chicken", "Sheep", "Cattle", "Horse"]
>>> json.loads('["Chicken", "Sheep", "Cattle", "Horse"]')
[u'Chicken', u'Sheep', u'Cattle', u'Horse']
1 голос
/ 28 августа 2010

pickle был разработан для этого.Используйте pickle.dump, чтобы записать объект в файл и pickle.load, чтобы прочитать его обратно.

>>> data
{'animals': ['Chicken', 'Sheep', 'Cattle', 'Horse'], 'population': [150, 200, 50, 30]}
>>> f = open('spam.p', 'wb')
>>> pickle.dump(data, f)
>>> f.close()
>>> f = open('spam.p', 'rb')
>>> pickle.load(f)
{'animals': ['Chicken', 'Sheep', 'Cattle', 'Horse'], 'population': [150, 200, 50, 30]}
0 голосов
/ 28 августа 2010

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

С помощью простых структур данных вы также можете выбрать json или yaml. Последний на самом деле довольно читабелен и доступен для редактирования.

...