Мне нужен способ хранения данных конфигурации системы, и я нашел его легким для понимания/понимания с помощью вложенных классов:
>>> class syscnf:
... class netwrk:
... class iface:
... class eth0:
... address = '192.168.0.100'
... netmask = '255.255.255.0'
... mtu = 1500
... class eth1:
... address = '172.25.0.23'
... netmask = '255.255.255.128'
... class route:
... default = '192.168.0.1'
>>>
>>> print syscnf.netwrk.iface.eth0.address
192.168.0.100
>>>
но эта структура не может быть маринована и сохранена. Я знаю, что могу отложить его в парах ключ/значение:
syscnf.netwrk.iface.eth0.address => 192.168.0.100
syscnf.netwrk.iface.eth0.netmask => 255.255.255.0
syscnf.netwrk.route.default => 192.168.0.1
syscnf.... etc
но похоже, что было бы сложно управлять и подвергать ошибкам?
или я мог бы сохранить его в sqlite DB, но тогда мне понадобится новая таблица, а схема для каждого конечного уровня данных конфигурации и хранения маринованных данных в sqlite кажется, что это будет сложно управлять.
Мне нужен способ сохранить эти данные на встроенной платформе, поэтому ему нужно передать на чистые python и включенные модули (или быть очень легко перекрестно компилировать - я не пробовал, но код ZODB читал, как будто бы это было бы легко скомпилировать и т.д.)
Что вы использовали, что было гибким и прямым? Это не должно быть высокой производительности, и concurrency будет приятным, но не "обязательным"
Мне никогда не приходилось делать что-либо подобное, и надеялся, что у вас, ребята, есть понимание/опыт, который вы хотели бы поделиться!
Я согласен с Ignacio Vazquez-Abrams в том, что использование JSON-подобной структуры облегчит работу, означая, что у вас может быть такая структура, как:
syscnf = {
'netwrk': {
'iface': {
'eth0': {
'address': '192.168.0.100',
'netmask': '255.255.255.0',
'mtu': 1500,
}
# ...
}
'route': {
'default': '192.168.0.1',
}
}
}
То есть, в основном словари в словарях (и другие значения, такие как строки, числа и списки). И тогда вам нужно будет получить доступ к таким элементам, как словари, а не к классам, например
print syscnf['netwrk']['iface']['eth0']['address']
вместо:
print syscnf.netwrk.iface.eth0.address
Затем вы можете просто использовать модуль json или simplejson (или даже старый добрый pickle/cPickle) для сериализации.
Конечно, вы теряете некоторую привлекательность и получаете кучу скобок. Если это важно для вас, вы можете попробовать что-то вроде YAML (доступен модуль Python), или вы можете сохранить то, что у вас есть, напишите конвертер, который рекурсивно заменяет класс словарем, связанным с memebers его dir(), удаляя такие вещи, как doc и модуль.
например.
from types import ClassType
def jsonize_class( klass ):
def recurse( child ):
return jsonize_class(child) if isinstance(child, ClassType) else child
def entry( key ):
return key, recurse( getattr(klass,key) )
return dict(( entry(key) for key in dir(klass) if not key.startswith('__') ))
который затем преобразует класс в формате, который вы уже используете, в json-подобную структуру:
>>> class bob:
... x = 9
... y = "hello"
... class job:
... bill = 999
... class rob:
... pass
...
>>> jsonize_class(bob)
{'y': 'hello', 'x': 9, 'job': {'bill': 999}, 'rob': {}}
Затем, чтобы взять сериализованный объект JSON и сделать его доступным в стиле, который вам нравится, вы можете изменить процесс:
from types import DictType
def classize_json( the_json ):
if isinstance( the_json, DictType ):
class returned_class: pass
for key, val in the_json.iteritems():
setattr( returned_class, key, classize_json(val) )
return returned_class
else:
return the_json
например:.
>>> jBob = jsonize_class(bob)
>>> jBob
{'y': 'hello', 'x': 9, 'job': {'bill': 999}, 'jimmy': 99, 'rob': {}}
>>> cBob = classize_json(jBob)
>>> cBob.y
'hello'
>>> cBob.job.bill
999
>>> cBob.jimmy
99
Все классные дети используют json
. Кроме того, если ваша структура использует экземпляры вместо простых классов, это значительно упростит сериализацию.