Далее предполагается, что вы используете Python3 (и вам следует, если вы изучаете Python), потому что он использует pathlib
, который находится в стандартной библиотеке для Python3.Существует пакет pathlib2
, который предоставляет эту функциональность для Python2.
Пример кода, который вы представляете, делает несколько странных вещей:
нет необходимости читать содержимое файла (open(...).read()
), а затем передать это методу .load()
, вы можете напрямую передать указатель файла (т. е. результат простого выполнения open()
, или вы можетеиспользуйте объект Path
и передайте его .load()
, даже не открывая файл (как показано ниже).
неясно, почему символ новой строки записывается в sys.stdout
, чтодействительно не имеет функции в этом фрагменте
вызов code.insert(1, 'sensor', 'None', comment="new key")
действительно помещает 'sensor' в качестве нового ключа, в позицию 1 словаря, подобного объекту code
со значением None
и комментарием к концу строки «новый ключ». (Подсчет позиций начинается с 0.
Если вы действительно запустили этот код, вы получитекак вывод:
# Employee records
Developer:
Department: IT
Manager: ABCD
Floor: 2nd
Lab: 4
sensor: None # new key
Support:
Department: General
Manager: XYZ
Floor: 1st
Lab: 1
Martin:
name: Martin Devloper
job: Developer
skills:
- python
В корне вашего входного файла находится отображение с ключами Developer
, Support
и Martin
.Значения, связанные с ключом, могут снова быть отображением (как в случае со всеми вашими ключами корневого уровня), но они также могут быть последовательностью (как и значение для skills
, обозначенное тире (-
)или скалярные значения (строка, число и т. д.).Корнем документа YAML может быть скаляр (который затем является единственным объектом в документе) или последовательность.И последовательность имеет элементы, которые могут быть скалярами (как ваша последняя строка python
), но эти элементы также могут быть отображениями или другими последовательностями.
Отображения загружаются как Python dict
s, последовательности загружаются какPython list
с.Чтобы сохранить комментарии (и другую информацию), ruamel.yaml
создаст диктант.объекты, похожие на списки, при использовании как в примере.Вы не сможете вызвать code.insert()
на обычном Python dict
, но вы можете сделать это на том, что получили (от YAML().load()
)
Если вы просто хотите добавить пару ключ-значениев конце дикта вам не нужно использовать .insert
, вы можете просто сделать:
code['Tabitha'] = dict(name='Tabitha Bitumen', job='Developer', skills=['Java'])
Если вам нужно переместить что-то в конец файла YAML, вы на самом деле не можете простообновите значение, например,
code['Support'] = dict(Department='General', Manager='KLM', Floor='1st', Lab=1)
, чтобы получить ключ / значение в старой позиции.Сначала вам нужно будет сделать
del code['Support']
, чтобы забыть эту старую позицию.
Как указано ruamel.yaml
поддерживает несколько способов чтения и записи в файл.Введенный оператор with
в качестве ответа Moralous
уже лучше, чем явное открытие, чтение и закрытие.Вы также можете использовать pathlib.Path
подобные объекты с методами .load()
и .dump()
:
from pathlib import Path
from ruamel.yaml import YAML
path = Path('inp.yaml') # I shortened this a bit, as I don't have a C: drive
opath = Path('outp.yaml')
yaml = YAML()
code = yaml.load(path)
code['Tabitha'] = dict(name='Tabitha Bitumen', job='Developer', skills=['Java'])
yaml.dump(code, opath)
, что дает:
# Employee records
Developer:
Department: IT
Manager: ABCD
Floor: 2nd
Lab: 4
Support:
Department: General
Manager: XYZ
Floor: 1st
Lab: 1
Martin:
name: Martin Devloper
job: Developer
skills:
- python
Tabitha:
name: Tabitha Bitumen
job: Developer
skills:
- Java
Это почти то, что вы хотите, ноОтступ по умолчанию для вывода YAML равен 2 позициям как для dict (как вы хотите, чтобы он был), так и для последовательности (он считается до начала вашего элемента, а не до тире).
Чтобы получитьчто вы хотите, вам нужно указать отступ в четыре для последовательности и смещение в два для тире с пробелами.Это можно сделать, вставив после строки yaml = YAML()
строку с:
yaml.indent(sequence=4, offset=2)
Вы также можете использовать сам экземпляр YAML
в операторе with
:
import sys
from pathlib import Path
from ruamel.yaml import YAML
path = Path('inp.yaml') # I shortened this a bit, as I don't have a C: drive
opath = Path('outp.yaml')
with YAML(output=opath) as yaml:
yaml.indent(sequence=4, offset=2)
code = yaml.load(path)
code['Tabitha'] = dict(name='Tabitha Bitumen', job='Developer', skills=['Java'])
yaml.dump(code)
Это также даст вам именно то, что вы хотите:
# Employee records
Developer:
Department: IT
Manager: ABCD
Floor: 2nd
Lab: 4
Support:
Department: General
Manager: XYZ
Floor: 1st
Lab: 1
Martin:
name: Martin Devloper
job: Developer
skills:
- python
Tabitha:
name: Tabitha Bitumen
job: Developer
skills:
- Java
Вы также пометили свой вопрос PyYAML.Пожалуйста, обратите внимание, что с этим пакетом вы не можете сделать выше: ваши комментарии в файле YAML будут потеряны, и у вас нет такого точного контроля над отступом, чтобы получить желаемый результат.