Как редактировать YAML-файл в python несколько раз, используя переменную без определения конкретного значения для ключа? - PullRequest
0 голосов
/ 17 ноября 2018

Это мой пример файла YAML,

# 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

Я хочу прочитать этот файл yaml из определенного каталога, отредактировать его, а затем сохранить отредактированный текст в том же файле yaml. Я получил этот код по ссылке где-то следующим образом:

import sys
from ruamel.yaml import YAML
inp_fo = open("C:/<Users>/Master 
1TB/source/repos/New_insertdata/PythonApplication3/inp.yaml").read() 
#Read the YAML File

yaml = YAML()
code = yaml.load(inp_fo)
sys.stdout.write('\n')
code.insert(1, 'sensor', 'None', comment="new key")
inp_fo2 = open("inp.yaml","w") #Open the file for Write
yaml.dump(code, inp_fo2) ##Write to file with new parameter
inp_fo2.close() ## close the file

Когда я выполняю его, я получаю вывод следующим образом:

# Employee records
Developer:
  Department: IT
  Manager: ABCD
  Floor: 2nd
  Lab: 4
Support:
  Department: General
  Manager: XYZ
  Floor: 1st
  Lab: 1
Martin:
  name: Martin 
  job: Developer
  skills:
    - python
Tabitha: None 

Но вместо этого мне нужно:

# Employee records
Developer:
  Department: IT
  Manager: ABCD
  Floor: 2nd
  Lab: 4
Support:
  Department: General
  Manager: XYZ
  Floor: 1st
  Lab: 1
Martin:
  name: Martin 
  job: Developer
  skills:
    - python
Tabitha:
  name: Tabitha Bitumen
  job: Developer
  skills:
    - Java

Как закодировать это?

Я ввел значение для Tabitha как None, потому что code.insert не выполнялся, если я не вставил значение для него.

Теперь я хочу несколько раз редактировать этот файл yaml, поэтому я хочу определить переменную для каждого значения ключа, поэтому каждый раз, когда значение переменной изменяется, код будет выполняться, и новые значения ключа будут вставляться в существующий файл yaml. Я не хочу удалять более раннее содержимое файла YAML, просто нужно продолжать добавлять новое содержимое (ключ и значение) (содержимое будет содержать сведения о сотруднике, такие как имя, должность, навыки).

Я совершенно новичок в этом языке кодирования, поэтому, если я ошибаюсь, поправьте меня. Также может кто-нибудь объяснить мне, как использовать отступ, последовательность и отображение в ruamel.yaml и как я могу использовать их в коде?

Я ученик, и приведенный выше пример представляет собой случайный файл yaml, просто пример для изучения ruamel.yaml.

Позвольте мне объяснить вам, что именно я хочу, Следующее содержимое останется статичным.

 # Employee records
Developer:
  Department: IT
  Manager: ABCD
  Floor: 2nd
  Lab: 4
Support:
  Department: General
  Manager: XYZ
  Floor: 1st
  Lab: 1

Но ключевые значения (данные сотрудника) изменятся. Пример, который я хочу: Мартин: имя: Мартин Девлопер работа: разработчик навыки: - питон

"Martin" should be a "variableP"
name: "variableQ"
job: "variableR"
skills:
  - "variableS"

аналогично, если другой сотрудник добавляет свои данные, код автоматически добавляет данные другого сотрудника в эти переменные. потому что согласно вашему коду мне придется многократно добавлять

code['Tabitha'] = dict(name='Tabitha Bitumen', job='Developer', skills=['Java'])

снова и снова для других данных о сотрудниках, которые мне не нужны, я просто хочу код, в котором я мог бы определить переменную, значение которой будет постоянно изменяться, и будет неоднократно редактировать один и тот же файл yaml и не удалять более ранние сведения о сотруднике , Нет ограничений на добавление списка сотрудников, поэтому я не хочу редактировать код снова и снова.

Я в основном знаю язык программирования C и arduino, поэтому ищу способ определения переменных в коде, который облегчит мою работу.

Ответы [ 2 ]

0 голосов
/ 17 ноября 2018

Далее предполагается, что вы используете 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 будут потеряны, и у вас нет такого точного контроля над отступом, чтобы получить желаемый результат.

0 голосов
/ 17 ноября 2018

Используемая вами библиотека YAML преобразует форматирование YAML в словари Python.Поэтому вы можете просто отредактировать словарь, чтобы добавить или изменить значение в файле YAML.Например:

import sys
from ruamel.yaml import YAML
filename = "C:/<Users>/Master/1TB/source/repos/New_insertdata/PythonApplication3/inp.yaml"

yaml = YAML()
with open(filename) as inp_fo:
    code = yaml.load(inp_fo)

    code["Tabitha"] = {
                        "name":"Tabitha Bitman",
                        "job":"Developer",
                        "skills":["Python"]
                      }

with open(filename, "w") as file:
    yaml.dump(code, file) ##Write to file with new parameter

Нет необходимости закрывать файлы, так как они были открыты в выражениях «with»

Это обновит данные Табиты в файле YAML, предполагая, что остальная часть вашего кода верна.

Вы также можете проанализировать переменную в ключе: поиск значения, заменив code["Tabitha"] на code[variable_name].

Если вы работаете сФайлы YAML (или JSON), я также настоятельно рекомендую изучить и понять словари в Python.

...