我有一个包含以下内容的 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)
我该如何解决这个问题?
最佳答案
您正在导入 os
、yaml
(即 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_quotes
、indent
、block_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 和端口,并连接这些值,而不是对 ip
和 port
值进行硬编码。我建议为此使用标准 python 模块 argparse
,但请注意,大多数应用程序只接受带有双破折号的长选项(--ip
而不是 -ip
)
关于python - 使用 python 在给定输入参数的文件中追加一行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44631061/