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?

+3


source to share


1 answer


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

)

+1


source







All Articles