问题
I have a use case where I need to pick key:value pairs from a new YAML file. Check whether that key exists in old YAML file and if it does copy the value and set it in new YAML file.
Also if that key does not exist in old file then ask the user.
Code:
copyfile('all.isv', '/home/ubuntu/tmp/deploy/all')
with open("/home/ubuntu/ansible-environments/aws/lp/all", 'r') as f1:
try:
oldvars = yaml.load(f1)
with open("/home/ubuntu/tmp/deploy/all", 'rw') as f2:
newvars = yaml.load(f2)
for key,value in newvars.items():
print key, ":", value
if key in f1:
value = oldvars.items(value)
print key,value
f2.write(value)
else:
value = raw_input("Enter the value ")
It's not working. Not able to understand how to check the key in old file and write value for that key in new file.
New File :
# Enter the release and build you wish to deploy
release: "4.0"
build: "4_0_178"
ems_release: "4.0"
ems_build: "4_0_982"
build_type: "gold_master"
# The name prefix is synonymous with the stack (i.e. pdx02-cloud-prod)
name_prefix: syd01-devops-test
# The deployment type is one of: [ test | trial | dev | prod ]
deployment_type: test
# deployment_url is typically the same value as deployment type unless it is a premium deployment.
# In that case deployment_type is set to prod and deployment_url is either dev, trial or test
deployment_url: "{{ deployment_type }}"
some_new_var: hello
Old File :
# Enter the release and build you wish to deploy
release: "4.0"
build: "4_0_178"
ems_release: "4.0"
ems_build: "4_0_999"
build_type: test_build
# The name prefix is synonymous with the stack (i.e. pdx02-cloud-prod)
name_prefix: syd01-devops-deepali
# The deployment type is one of: [ test | trial | dev | prod ]
deployment_type: trial
# deployment_url is typically the same value as deployment type unless it is a premium deployment.
# In that case deployment_type is set to prod and deployment_url is either dev, trial or test
deployment_url: "{{ deployment_type }}"
Expected: File generated using two files(old and new)
# Enter the release and build you wish to deploy
release: "4.0"
build: "4_0_178"
ems_release: "4.0"
ems_build: "4_0_999"
build_type: test_build
# The name prefix is synonymous with the stack (i.e. pdx02-cloud-prod)
name_prefix: syd01-devops-deepali
# The deployment type is one of: [ test | trial | dev | prod ]
deployment_type: trial
# deployment_url is typically the same value as deployment type unless it is a premium deployment.
# In that case deployment_type is set to prod and deployment_url is either dev, trial or test
deployment_url: "{{ deployment_type }}"
some_new_var: Value provided by user as input
回答1:
That is invalid Python, your try
doesn't have a matching except
. Apart from that it is not necessary to open the second file in the context of the with statement that you use for reading in the "old" file. Therefore start with:
import ruamel.yaml
copyfile('all.isv', '/home/ubuntu/tmp/deploy/all')
with open("/home/ubuntu/ansible-environments/aws/lp/all", 'r') as f1:
oldvars = ruamel.yaml.round_trip_load(f1)
You cannot open a YAML file for reading and writing, therefore just read it (and opening for reading and writing of a file is done with 'r+' not with 'rw'):
with open("/home/ubuntu/tmp/deploy/all", 'r') as f2:
newvars = ruamel.yaml.round_trip_load(f2)
After that continue unindented and update newvars from oldvars if appropriate:
for key in newvars:
if key in oldvars:
# this copies the value from the old file if the key exists in there
value = oldvars[key]
else:
# ask the user for a new value
value = raw_input("Enter the value ")
# update the value in newvars
newvars[key] = value
# and write the update mapping back
with open("/home/ubuntu/tmp/deploy/all", 'w') as f2:
ruamel.yaml.round_trip_dump(newvars, f2)
Combining that and naming your files old.yaml
and new.yaml
and answering the prompt with 'abcd
':
import sys
import ruamel.yaml
with open('new.yaml') as fp:
newvars = ruamel.yaml.round_trip_load(fp)
with open('old.yaml') as fp:
oldvars = ruamel.yaml.round_trip_load(fp)
for key in newvars:
if key in oldvars:
# this copies the value from the old file if the key exists in there
value = oldvars[key]
else:
# ask the user for a new value
value = raw_input("Enter the value ")
# update the value in newvars
newvars[key] = value
ruamel.yaml.round_trip_dump(newvars, sys.stdout)
gives you:
Enter the value abcd
# Enter the release and build you wish to deploy
release: '4.0'
build: '4_0_178'
ems_release: '4.0'
ems_build: '4_0_999'
build_type: test_build
# The name prefix is synonymous with the stack (i.e. pdx02-cloud-prod)
name_prefix: syd01-devops-deepali
# The deployment type is one of: [ test | trial | dev | prod ]
deployment_type: trial
# deployment_url is typically the same value as deployment type unless it is a premium deployment.
# In that case deployment_type is set to prod and deployment_url is either dev, trial or test
deployment_url: '{{ deployment_type }}'
some_new_var: abcd
Please note that:
- this only runs on Python 2.7
- for scalars that do not need them quotes are dropped
- I did not try to include the four space indentation of your output past the first line.
来源:https://stackoverflow.com/questions/37661712/copy-content-from-one-yaml-to-another-yaml-after-comparison-of-keys