I want to change only the attribute anotherName from the following yaml file with python.
test.yaml:
---
kind: test
scope: not far
spec:
test1:
options:
- name: test.com
anotherName: example.com
empty: []
groupOne: []
emptyList:
firstList: []
secondList: []
Code (based on this answer)
import yaml
with open("test.yaml", 'r') as stream:
try:
loaded=yaml.safe_load(stream)
except yaml.YAMLError as exc:
print(exc)
temp= loaded['spec']['test1']['options']
for elem in temp:
elem['anotherName']='somethingChanged'
with open("modified.yaml", 'w') as stream:
try:
yaml.dump(loaded, stream)
print(loaded)
except yaml.YAMLError as exc:
print(exc)
The value has been changed, but the code change the order and the structure of the modified.yaml :
#First it misses the thre dashes
kind: test
scope: not far
spec:
test1:
emptyList:
firstList: []
secondList: []
groupOne: []
options:
- anotherName: somethingChanged #then the order is changed
empty: []
name: test.com
CodePudding user response:
you can probably not force a specific output from pyyaml, but if you have such a specific requirement what you want to substitute, then why make the extra hassel of parsing the yml fromat at all. How about reading the file into a string and then making your replacement:
import re
# Here you would need to read the file content. I define it here
content="""
---
kind: test
scope: not far
spec:
test1:
options:
- name: test.com
anotherName: example.com
empty: []
groupOne: []
emptyList:
firstList: []
secondList: []
"""
print(re.sub(r'anotherName: [^\n]*', 'anotherName: somethingChanged', content))
Output:
---
kind: test
scope: not far
spec:
test1:
options:
- name: test.com
anotherName: somethingChanged
empty: []
groupOne: []
emptyList:
firstList: []
secondList: []
CodePudding user response:
If your version of PyYAML is higher than 5.1 you can use sort_keys
argument to preserve the order. The only line that needs change is this one:
yaml.dump(loaded, stream, sort_keys=False)