使用 python ruamel-yaml 保持 YAML 文件的偏移缩进
Keeping offset indentation of YAML file using python ruamel-yaml
我正在尝试使用 ruamel-yaml 来实现以下目标我有一个包含一组变量的 YAML 文件,如下所示(请注意所有键都以缩进 6 开头):
app:
version: 'latest'
env: 'test'
#auth
auth_endpoint: 'http://localhost/login'
auth_token: 23NSDQD94NFDFKF0SQS
我的想法是为用户提供一个 python 脚本,该脚本将生成配置文件但具有覆盖的值,所以基本上我将解析参数,加载 YAML 文件更改值并转储 YAML 文件使用更新后的值,一切正常,除了当文件被转储时,6 的缩进丢失,除了评论,(见下面的代码)
app:
version: 'latest'
env: 'test'
#auth
auth_endpoint: 'http://localhost/login'
auth_token: 23NSDQD94NFDFKF0SQS
现在这个缩进很重要,因为这个文件随后将被解析并合并到一个更大的 YAML 文件中
def update_yaml(file):
yaml = ruamel.yaml.YAML()
yaml.indent(mapping=6)
config_yaml = yaml.load(file)
# value changing code ommited for readability
with open(os.path.join(sys.path[0], "config.yml"), 'w') as file:
yaml.dump(config_yml, file)
我已经尝试了一些缩进方法,但都无济于事,知道如何才能保持原来的缩进吗?
首先,你的所有键的缩进都是6是不正确的,因为
键 version
和 env
,它们是映射的一部分,是值
根级键 app
, 仅缩进两个位置 .
ruamel.yaml
将强制您的输出在缩进方面保持一致。所有映射都将缩进相同,所有序列也是如此(尽管映射和序列可以不同)。因为你想要的输出是
不一致,你需要做一些 post 处理:
import sys
import ruamel.yaml
yaml_str = """\
app:
version: 'latest'
env: 'test'
#auth
auth_endpoint: 'http://localhost/login'
auth_token: 23NSDQD94NFDFKF0SQS
"""
class PushRootLeft:
def __init__(self, positions=42):
self.positions = positions
def __call__(self, s):
result = []
for line in s.splitlines(True):
sline = line.strip()
if not sline or sline[0] == '#':
result.append(line)
else:
result.append(' ' * self.positions + line)
return ''.join(result)
yaml = ruamel.yaml.YAML()
yaml.indent(mapping=2) # not necessary, this is the default
yaml.preserve_quotes = True
data = yaml.load(yaml_str)
print('123456780') # just to better see the alignment of the actual YAML output
yaml.dump(data, sys.stdout, transform=PushRootLeft(6))
给出:
123456780
app:
version: 'latest'
env: 'test'
#auth
auth_endpoint: 'http://localhost/login'
auth_token: 23NSDQD94NFDFKF0SQS
您应该设置 .preserve_quotes
,因为某些(损坏的)解析器不喜欢 URL 中的冒号未加引号,
将其解释为价值指标,即使它后面没有 space.
你必须对评论做一些特别的事情是因为在往返过程中它知道它最初出现在哪一列并且会尝试在那里恢复(除非一些值的变化将它推向正确)。
自 2006 年 9 月以来 recommended extension for YAML files has been .yaml
。
我正在尝试使用 ruamel-yaml 来实现以下目标我有一个包含一组变量的 YAML 文件,如下所示(请注意所有键都以缩进 6 开头):
app:
version: 'latest'
env: 'test'
#auth
auth_endpoint: 'http://localhost/login'
auth_token: 23NSDQD94NFDFKF0SQS
我的想法是为用户提供一个 python 脚本,该脚本将生成配置文件但具有覆盖的值,所以基本上我将解析参数,加载 YAML 文件更改值并转储 YAML 文件使用更新后的值,一切正常,除了当文件被转储时,6 的缩进丢失,除了评论,(见下面的代码)
app:
version: 'latest'
env: 'test'
#auth
auth_endpoint: 'http://localhost/login'
auth_token: 23NSDQD94NFDFKF0SQS
现在这个缩进很重要,因为这个文件随后将被解析并合并到一个更大的 YAML 文件中
def update_yaml(file):
yaml = ruamel.yaml.YAML()
yaml.indent(mapping=6)
config_yaml = yaml.load(file)
# value changing code ommited for readability
with open(os.path.join(sys.path[0], "config.yml"), 'w') as file:
yaml.dump(config_yml, file)
我已经尝试了一些缩进方法,但都无济于事,知道如何才能保持原来的缩进吗?
首先,你的所有键的缩进都是6是不正确的,因为
键 version
和 env
,它们是映射的一部分,是值
根级键 app
, 仅缩进两个位置 .
ruamel.yaml
将强制您的输出在缩进方面保持一致。所有映射都将缩进相同,所有序列也是如此(尽管映射和序列可以不同)。因为你想要的输出是
不一致,你需要做一些 post 处理:
import sys
import ruamel.yaml
yaml_str = """\
app:
version: 'latest'
env: 'test'
#auth
auth_endpoint: 'http://localhost/login'
auth_token: 23NSDQD94NFDFKF0SQS
"""
class PushRootLeft:
def __init__(self, positions=42):
self.positions = positions
def __call__(self, s):
result = []
for line in s.splitlines(True):
sline = line.strip()
if not sline or sline[0] == '#':
result.append(line)
else:
result.append(' ' * self.positions + line)
return ''.join(result)
yaml = ruamel.yaml.YAML()
yaml.indent(mapping=2) # not necessary, this is the default
yaml.preserve_quotes = True
data = yaml.load(yaml_str)
print('123456780') # just to better see the alignment of the actual YAML output
yaml.dump(data, sys.stdout, transform=PushRootLeft(6))
给出:
123456780
app:
version: 'latest'
env: 'test'
#auth
auth_endpoint: 'http://localhost/login'
auth_token: 23NSDQD94NFDFKF0SQS
您应该设置 .preserve_quotes
,因为某些(损坏的)解析器不喜欢 URL 中的冒号未加引号,
将其解释为价值指标,即使它后面没有 space.
你必须对评论做一些特别的事情是因为在往返过程中它知道它最初出现在哪一列并且会尝试在那里恢复(除非一些值的变化将它推向正确)。
自 2006 年 9 月以来 recommended extension for YAML files has been .yaml
。