[PYTHON] 동일한 키에 대해 여러 값을 유지하면서 파일을 구성하는 방법은 무엇입니까?
PYTHON동일한 키에 대해 여러 값을 유지하면서 파일을 구성하는 방법은 무엇입니까?
ConfigParser를 사용하여 동일한 키에 대해 여러 값을 읽을 수 있어야합니다. 구성 파일 예제 :
[test]
foo = value1
foo = value2
xxx = yyy
ConfigParser를 '표준'으로 사용하면 값이 value2 인 키 foo가 하나 있습니다. 하지만 파서가 두 값을 모두 읽어야합니다.
중복 키에 대한 항목 다음에 다음 예제 코드를 작성했습니다.
from collections import OrderedDict
from ConfigParser import RawConfigParser
class OrderedMultisetDict(OrderedDict):
def __setitem__(self, key, value):
try:
item = self.__getitem__(key)
except KeyError:
super(OrderedMultisetDict, self).__setitem__(key, value)
return
print "item: ", item, value
if isinstance(value, list):
item.extend(value)
else:
item.append(value)
super(OrderedMultisetDict, self).__setitem__(key, item)
config = RawConfigParser(dict_type = OrderedDict)
config.read(["test.cfg"])
print config.get("test", "foo")
print config.get("test", "xxx")
config2 = RawConfigParser(dict_type = OrderedMultisetDict)
config2.read(["test.cfg"])
print config2.get("test", "foo")
print config.get("test", "xxx")
첫 번째 부분 (config 포함)은 config 파일에서 'ordinary'를 읽으며 foo (다른 값을 덮어 쓰거나 삭제)의 값으로 value2 만 남겨두고 다음과 같은 예상 결과를 얻습니다.
value2
yyy
두 번째 부분 (config2) 내 접근 방식을 사용하여 목록에 여러 값을 추가하지만 출력 대신
['value1', 'value2', 'value1\nvalue2']
['yyy', 'yyy']
반복되는 값을 제거하려면 어떻게해야합니까? 출력을 다음과 같이 예상합니다.
['value1', 'value2']
yyy
또는
['value1', 'value2']
['yyy']
(나는 모든 가치가 목록에 있다면 상관 없다 ...). 어떤 제안이라도 환영합니다.
해결법
-
==============================
1.작은 수정을 통해, 나는 당신이 원하는 것을 얻을 수있었습니다 :
작은 수정을 통해, 나는 당신이 원하는 것을 얻을 수있었습니다 :
class MultiOrderedDict(OrderedDict): def __setitem__(self, key, value): if isinstance(value, list) and key in self: self[key].extend(value) else: super(MultiOrderedDict, self).__setitem__(key, value) # super().__setitem__(key, value) in Python 3 config = ConfigParser.RawConfigParser(dict_type=MultiOrderedDict) config.read(['a.txt']) print config.get("test", "foo") print config.get("test", "xxx")
출력 :
['value1', 'value2'] ['yyy']
-
==============================
2.허용 된 응답은 config.sections ()를 깨고 항상 빈 목록 (Python 3.5.3에서 테스트 됨)을 반환합니다. super () .__ setitem __ (key, value)에 의해 super (OrderedDict, self) .__ setitem __ (key, value)를 대체하지만, 이제는 config.get (section, key)가 더 이상 문자열 목록이 아닌 연결된 문자열을 반환합니다.
허용 된 응답은 config.sections ()를 깨고 항상 빈 목록 (Python 3.5.3에서 테스트 됨)을 반환합니다. super () .__ setitem __ (key, value)에 의해 super (OrderedDict, self) .__ setitem __ (key, value)를 대체하지만, 이제는 config.get (section, key)가 더 이상 문자열 목록이 아닌 연결된 문자열을 반환합니다.
내 솔루션은 다음과 같습니다.
class ConfigParserMultiValues(collections.OrderedDict): def __setitem__(self, key, value): if key in self and isinstance(value, list): self[key].extend(value) else: super().__setitem__(key, value) @staticmethod def getlist(value): return value.split(os.linesep) config = configparser.ConfigParser(strict=False, empty_lines_in_values=False, dict_type=ConfigParserMultiValues, converters={"list": ConfigParserMultiValues.getlist}) ... values = config.getlist("Section", "key") # => ["value1", "value2"]
구성 INI 파일은 중복 키를 허용합니다.
[Section] key = value1 key = value2
-
==============================
3.@ abarnert의 대답으로 약간 변경됩니다. 그렇지 않으면 __setitem__을 반복적으로 호출하고 어떤 이유로 중지되지 않습니다.
@ abarnert의 대답으로 약간 변경됩니다. 그렇지 않으면 __setitem__을 반복적으로 호출하고 어떤 이유로 중지되지 않습니다.
이 파일 :
[section] key1 = value1 key2[] = value21 key2[] = value22
파이썬 :
class MultiOrderedDict(OrderedDict): LIST_SUFFIX = '[]' LIST_SUFFIX_LEN = len(LIST_SUFFIX) def __setitem__(self, key, value): if key.endswith(self.LIST_SUFFIX): values = super(OrderedDict, self).setdefault(key, []) if isinstance(value, list): values.extend(value) else: values.append(value) else: super(MultiOrderedDict, self).__setitem__(key, value) def __getitem__(self, key): value = super(MultiOrderedDict, self).__getitem__(key) if key.endswith(self.LIST_SUFFIX) and not isinstance(value, list): value = value.split('\n') return value
테스트:
def test_ini(self): dir_path = os.path.dirname(os.path.realpath(__file__)) config = RawConfigParser(dict_type=MultiOrderedDict, strict=False) config.readfp(codecs.open('{}/../config/sample.ini'.format(dir_path), encoding="utf_8_sig")) self.assertEquals(config.get("section1", "key1"), 'value1') self.assertEquals(config.get("section1", "key2[]"), ['value21', 'value22'])
-
==============================
4.더 많은 예제 test.cfg의 여러 값.
더 많은 예제 test.cfg의 여러 값.
[test] foo = value1 foo = value2 value3 xxx = yyy
value3 식품 목록에 값을 추가합니다. ConfigParser는 목록을 문자열로 변환합니다.
/usr/lib/python2.7/ConfigParser.pyc in _read(self, fp, fpname) 552 for name, val in options.items(): 553 if isinstance(val, list): --> 554 options[name] = '\n'.join(val) 555
변환 전 값은 항상 list 또는 dict (MultiOrderedDict)입니다.
이것을 시도해보십시오 - config.items가 작동합니다 :
from collections import OrderedDict import ConfigParser class MultiOrderedDict(OrderedDict): def __setitem__(self, key, value): if key in self: if isinstance(value, list): self[key].extend(value) return elif isinstance(value,str): return # ignore conversion list to string (line 554) super(MultiOrderedDict, self).__setitem__(key, value) config = ConfigParser.RawConfigParser(dict_type=MultiOrderedDict) config.read(['test.cfg']) print config.get("test", "foo") print config.get("test", "xxx") print config.items("test")
출력 :
['value1', 'value2', 'value3'] ['yyy'] [('foo', ['value1', 'value2', 'value3']), ('xxx', ['yyy'])]
또 다른 구현 MultiOrderedDict
class MultiOrderedDict(OrderedDict): def __setitem__(self, key, value): if key in self: if isinstance(value, list): self[key].extend(value) return elif isinstance(value,str): if len(self[key])>1: return super(MultiOrderedDict, self).__setitem__(key, value)
출력 :
['value1', 'value2', 'value3'] yyy [('foo', ['value1', 'value2', 'value3']), ('xxx', 'yyy')]
from https://stackoverflow.com/questions/15848674/how-to-configparse-a-file-keeping-multiple-values-for-identical-keys by cc-by-sa and MIT license
'PYTHON' 카테고리의 다른 글
[PYTHON] Paramiko : NAT 라우터 주변의 포트 포워딩 (0) | 2018.11.09 |
---|---|
[PYTHON] SciPy의 지수 곡선 피팅 (0) | 2018.11.09 |
[PYTHON] 파이썬 사전에 항목을 삭제 한 후 메모리를 되찾기 (0) | 2018.11.09 |
[PYTHON] 지수 형식 / 과학 표기법이 아닌 일반 형식으로 부동 소수점 숫자 인쇄 (0) | 2018.11.09 |
[PYTHON] 파이썬에서 모든 예외를 잡기위한 나쁜 생각 (0) | 2018.11.09 |