2010-08-28 1 views
3

Я читаю файл XML и реорганизовать нужные данные в структуры Python данных (списки, кортежи и т.д.)Как сохранить и восстановить исходные структуры данных 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, но я не знаю, как заставить его работать. Если это правильный инструмент для использования, пример кода будет очень полезен. Могут быть и другие инструменты, которые я пока не знаю.

ответ

5

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, если хотите ;-) с нулевыми значениями , которые действительно представляют интерес, вместо того, чтобы использовать «оптовый» подход.

+0

+1 для дополнительной информации о 'globals()'. Что-то новое для меня :) – Kit

2

Травление хорошее, если у вас есть объекты, специфичные для 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

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

Я вижу, что вы преобразовали 'data' в другую структуру, которую я бы хотел избежать, поскольку мои данные уже структурированы в довольно сложных вложенных списках. Есть ли способ сделать 'data_miner.py' делать что-то в конце, например,« сохранить все переменные в моей области »и« сохранить его в каком-то двоичном файле »? – Kit

+0

Вы можете использовать 'locals()', чтобы получить 'dict', содержащий все локальные переменные. – dan04

0

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

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

+0

Кстати, вы также можете хранить сложные структуры данных в JSON и YAML. –

+0

Но не произвольные объекты (кроме несериализуемых вообще) со ссылками (возможно, круговыми) и т. Д. Правильно? –