使用python在给定输入参数的文件中追加一行

时间:2017-06-19 12:49:07

标签: python python-2.7 python-3.x yaml

我有一个YAML文件,其中包含以下内容:

job_name: "node"
scrape_interval: "15s"
static_configs:
  -  targets: ['10.10.10.11:8080']

现在如果我执行我的python脚本,它应该使用给定的参数

在YAML文件中追加目标行
i.e script.py -ip 10.10.20.30 -p 8181

文件应该如下所示

job_name: "node"
scrape_interval: "15s"
static_configs:
  -  targets: ['10.10.10.11:8080', '10.10.20.30:8181']

为此我使用下面的python脚本,但是它给出了错误:

#!/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)

我该如何解决这个问题?

1 个答案:

答案 0 :(得分:1)

您正在导入osyaml(即PyYAML),但您没有使用这些软件包。

您还尝试"编辑" YAML文件好像是非结构化文本,你不应该。相反,您应该加载YAML文件,然后扩展您获得的数据结构,然后将数据结构转储回YAML文件,但不能转移到PyYAML,因为它不支持这种往返而不会丢失信息。

而是使用ruamel.yaml(免责声明:我是该软件包的作者):

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)

将写下:

job_name: "node"
scrape_interval: "15s"
static_configs:
  -  targets: ['10.10.10.11:8080', '10.10.20.30:8181']

仅需要设置属性preserve_quotesindentblock_seq_indent以使输出与您的输入相匹配。复制类型也是如此 第一个targets元素。实际上,您的文件中没有引号。

如果有一个更加默认的YAML输出文件,它将加载到相同的数据,你可以这样做:

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)

请注意,多个条目映射中的键顺序以及YAML文件中的任何注释都将通过上述往返保留。

您当然仍需要从命令行获取IP和端口,并连接值而不是对ipport值进行硬编码。我建议使用标准的python模块argparse,但要注意大多数应用程序只使用双破折号(--ip而不是-ip)来选择长选项。