2015-01-26 5 views
1

Мне нужно написать структуру данных, хранящуюся как namedtuple, в файл и прочитать его как namedtuple в python.Запись и чтение namedtuple в файл в python

Решения здесь предлагают использовать Json.load/loads или pickle, которые записывают переменную как json key-value pair в виде строк. Тем не менее, все мои обращения/разметки полей имеют вид struct.key (а не struct["key"], который является способом доступа к значениям json), и это невозможно для исправления этого кода.

Я хочу сохранить это в файл, потому что структура огромна и занимает много времени, чтобы сгенерировать.

+1

Рассол не имеет ничего общего с json. Если вы выберете объект namedtuple для файла, вы также сможете прочитать его обратно из файла как namedtuple. – sebastian

+0

Как сказал @sebastian - использование 'pickle' будет самым простым - если вы действительно хотели JSON (может быть, это было доступно для чтения/редактирования), тогда вы можете обойти« namedtuple », но для этого более ресурсоемким , –

+0

group_t = namedtuple ('group', 'field1, field2'); Myobj = group_t (field1 = val1, field2 = val2) Я получаю a can not pickle он не найден как __main__.group. – amitp

ответ

3

Как раз обращаясь к вашей трудности с травлением, кажется, что для работы pickle.dumps() для работы требуется, чтобы аргумент typename для namedtuple соответствовал имени, к которому привязан возвращаемый класс.

import pickle 
from collections import namedtuple 

group_t = namedtuple('group_t', 'field1, field2') 
Myobj = group_t(field1=1, field2=2) 

>>> pickle.dumps(Myobj) 
'ccopy_reg\n_reconstructor\np0\n(c__main__\ngroup_t\np1\nc__builtin__\ntuple\np2\n(I1\nI2\ntp3\ntp4\nRp5\n.' 

Сравните с этим:

mismatched_group_t = namedtuple('group_t', 'field1, field2') 
Myobj = mismatched_group_t(field1=1, field2=2) 
>>> pickle.dumps(Myobj) 
Traceback (most recent call last): 
. 
. 
pickle.PicklingError: Can't pickle <class '__main__.group_t'>: it's not found as __main__.group_t 

Разница между этими двумя классами:

>>> group_t.__name__ 
'group_t' 
>>> mismatched_group_t.__name__ 
'group_t' 

Я бы сказал, что это то, что бросает pickle прочь.

+1

Похоже, что 'pickle' пытается получить доступ к классу в текущей области. Что произойдет, если метод вернул 'namedtuple', а класс был определен в другом месте и не импортирован, или, может быть, [даже не хранился нигде] (http://stackoverflow.com/q/17921869/1394393)? – jpmc26

9

Поскольку стандартные модули JSON в Python обычно используют dict для работы с объектами JSON, вам необходимо преобразовать их в dict.

Для небольшой установки, скажем, я создал этот namedtuple:

>>> from collections import namedtuple 
>>> import json 
>>> X = namedtuple('X', ['x', 'y', 'z']) 
>>> x = X(1,2,3) 
>>> x 
X(x=1, y=2, z=3) 

1) Используйте _asdict() преобразовать в dict, что вы можете сбросить в формате JSON:

>>> j = json.dumps(x._asdict()) 
>>> j 
'{"x": 1, "y": 2, "z": 3}' 

Теперь вам имеют представление JSON.

2) Для того, чтобы получить его обратно в объект, использовать ** для преобразования dict в именованные аргументы:

>>> x2 = X(**json.loads(j)) 
>>> x2 
X(x=1, y=2, z=3) 

Done. Конечно, вы можете читать/записывать JSON в файл любым способом. (Например, модули JSON имеют методы, которые напрямую работают с файлами.)