Add line to file with given input arguments using python
I have a YAML file with the content below:
job_name: "node"
scrape_interval: "15s"
static_configs:
- targets: ['10.10.10.11:8080']
now if i execute my python script it should add target line to YAML file using given arguments
i.e script.py -ip 10.10.20.30 -p 8181
the file should look like this
job_name: "node"
scrape_interval: "15s"
static_configs:
- targets: ['10.10.10.11:8080', '10.10.20.30:8181']
for this I am using the python script below, but it gives errors:
#!/usr/bin/python
import os
import yaml
with open('test.yaml', 'ra') as f:
lines = f.readlines()
for i, line in enumerate(lines):
if line.startswith('targets:'):
line[i] = line[i].strip() + 'arg1,arg2\n'
f.seek(0)
for line in lines:
f.write(line)
How can I fix this?
source to share
You import os
, yaml
(i.e. PyYAML), but you are not using those packages.
You are also trying to "edit" the YAML file as if it were unstructured text, and you shouldn't. Instead, you have to load the YAML file and then extend the data structure you get, then put the data structure back into the YAML file, but not with PyYAML, as it doesn't support this kind of round trip without losing information.
Use instead ruamel.yaml
(disclaimer: I am the author of this package):
from ruamel.yaml import YAML
yaml = YAML()
yaml.preserve_quotes = True
yaml.indent = 5
yaml.block_seq_indent = 2
ip = '10.10.20.30' # sys.argv[2]
port = 8181 # sys.argv[4]
with open('test.yaml') as f:
data = yaml.load(f)
targets = data['static_configs'][0]['targets']
targets.append(type(targets[0])(str(ip) + ':' + str(port)))
with open('test.yaml', 'w') as fo:
yaml.dump(data, fo)
What will write:
job_name: "node"
scrape_interval: "15s"
static_configs:
- targets: ['10.10.10.11:8080', '10.10.20.30:8181']
Setting attributes preserve_quotes
, indent
, block_seq_indent
need only to match the result of your input. The type of the first element is also copied targets
. None of the quotes in your file are actually required.
If a more standard YAML output file that will load on the same data is ok, you can do:
from ruamel.yaml import YAML
yaml = YAML()
ip = '10.10.20.30' # sys.argv[2]
port = 8181 # sys.argv[4]
with open('test.yaml') as f:
data = yaml.load(f)
data['static_configs'][0]['targets'].append(str(ip) + ':' + str(port))
with open('test.yaml', 'w') as fo:
yaml.dump(data, fo)
Note that both the key order in multiple post mappings and any comments in your YAML file will be preserved as a result of the above round.
Of course, you will still need to get the IP and port from the command line and concatenate the values instead of hardcoding the values ip
and port
. I suggest using the standard python module argparse
for this, but be careful that most applications only take long double-dash options ( --ip
instead of -ip
)
source to share