Я бы сказал, что это ошибка в PyYAML.Код ошибки: здесь :
def construct_mapping(self, node, deep=False):
if not isinstance(node, MappingNode):
raise ConstructorError(None, None,
"expected a mapping node, but found %s" % node.id,
node.start_mark)
mapping = {}
for key_node, value_node in node.value:
key = self.construct_object(key_node, deep=deep)
if not isinstance(key, collections.Hashable):
raise ConstructorError("while constructing a mapping", node.start_mark,
"found unhashable key", key_node.start_mark)
value = self.construct_object(value_node, deep=deep)
mapping[key] = value
return mapping
Понятно, что не проверяется, существует ли ключ.Вам нужно было бы создать подкласс Constructor
, чтобы создать тот, который имеет construct_mapping()
с включенной проверкой:
if key in mapping:
warnings.warn(somewarning)
else:
mapping[key] = value
, а затем создать Loader
, используя этот Constructor
.
Возможно, будет проще использовать ruamel.yaml
(отказ от ответственности: я являюсь автором этого пакета).Он корректно загружает это, предполагая, что вы отключили DuplicateKeyError
и явно задали YAML 1.1 в качестве входного формата:
import sys
import ruamel.yaml
yaml_file = Path('xx.yaml')
yaml = ruamel.yaml.YAML()
yaml.version = (1, 1)
yaml.indent(mapping=3, sequence=2, offset=0)
yaml.allow_duplicate_keys = True
data = yaml.load(yaml_file)
assert data['xxx']['aaa'] == 9
yaml_out = ruamel.yaml.YAML()
yaml_out.dump(data, sys.stdout)
Это дает:
xxx:
aaa: 9
bbb: 10
ccc: 11
Ваши восьмеричные будут преобразованы вдесятичные дроби (обычно эта информация сохраняется, но не при загрузке устаревшего YAML 1.1).PyYAML всегда будет делать это.