モジュールの動作を模倣してConfigParser
、使用する特定のアプリケーションの構成ファイル内の明確に定義された構造を活用する、高度に専門化されたパーサーを作成しています。構成ファイルのいくつかのセクションには、次のように、Variable_
またはのいずれかで始まる数百の変数とルーチンのマッピングが含まれています。Routine_
[Map.PRD]
Variable_FOO=LOC1
Variable_BAR=LOC2
Routine_FOO=LOC3
Routine_BAR=LOC4
...
[Map.SHD]
Variable_FOO=LOC1
Variable_BAR=LOC2
Routine_FOO=LOC3
Routine_BAR=LOC4
...
各セクションが単一の辞書として格納される基本構造を維持したいConfigParser
ので、ユーザーは引き続き従来の構文にアクセスできます。
config.content['Mappings']['Variable_FOO'] = 'LOC1'
このセクションにドリルダウンする簡略化された API を使用することもできます。
config.vmapping('PRD')['FOO'] = 'LOC1'
config.vmapping('PRD')['BAR'] = 'LOC2'
config.rmapping('PRD')['FOO'] = 'LOC3'
config.rmapping('PRD')['BAR'] = 'LOC4'
現在、属性dict
を追加した特別なサブクラスにセクションを格納することで、これを実装しています。パーサーprefix
のvariable
およびプロパティは、 のようなオブジェクトの属性をorに設定し、次に変更されたハンドルの属性は、適切なアイテムにアクセスするためのキーとプレフィックスを結び付けます。それは機能していますが、反復のサポートなど、関連するすべての機能を実装するために多くのボイラープレートが必要です。routine
prefix
dict
'Variable_'
'Routine_'
__getitem__
__setitem__
dict
私の理想的な解決策は、サブクラスdict
化されたものを省き、variable
とプロパティがプレフィックスなしで下にroutine
あるプレーンなオブジェクトの「ビュー」を何らかの方法で提示することだと思います。dict
アップデート
主に@abarnetの回答に基づいて、私が実装したソリューションを次に示します。
class MappingDict(object):
def __init__(self, prefix, d):
self.prefix, self.d = prefix, d
def prefixify(self, name):
return '{}_{}'.format(self.prefix, name)
def __getitem__(self, name):
name = self.prefixify(name)
return self.d.__getitem__(name)
def __setitem__(self, name, value):
name = self.prefixify(name)
return self.d.__setitem__(name, value)
def __delitem__(self, name):
name = self.prefixify(name)
return self.d.__delitem__(name)
def __iter__(self):
return (key.partition('_')[-1] for key in self.d
if key.startswith(self.prefix))
def __repr__(self):
return 'MappingDict({})'.format(dict.__repr__(self))
class MyParser(object):
SECTCRE = re.compile(r'\[(?P<header>[^]]+)\]')
def __init__(self, filename):
self.filename = filename
self.content = {}
lines = [x.strip() for x in open(filename).read().splitlines()
if x.strip()]
for line in lines:
match = re.match(self.SECTCRE, line)
if match:
section = match.group('header')
self.content[section] = {}
else:
key, sep, value = line.partition('=')
self.content[section][key] = value
def write(self, filename):
fp = open(filename, 'w')
for section in sorted(self.content, key=sectionsort):
fp.write("[%s]\n" % section)
for key in sorted(self.content[section], key=cpfsort):
value = str(self.content[section][key])
fp.write("%s\n" % '='.join([key,value]))
fp.write("\n")
fp.close()
def vmapping(self, nsp):
section = 'Map.{}'.format(nsp)
return MappingDict('Variable', self.content[section])
def rmapping(self, nsp):
section = 'Map.{}'.format(nsp)
return MappingDict('Routine', self.content[section])
次のように使用されます。
config = MyParser('myfile.cfg')
vmap = config.vmapping('PRD')
vmap['FOO'] = 'LOC5'
vmap['BAR'] = 'LOC6'
config.write('newfile.cfg')
結果はとの変更newfile.cfg
を反映します。LOC5
LOC6