Python yaml 在引号中生成几个值
Python yaml generate few values in quotes
我在 Python 脚本中使用 yaml
模块生成 YAML 文件。下面是一个例子:
import yaml
class MyDumper(yaml.Dumper):
def increase_indent(self, flow=False, indentless=False):
return super(MyDumper, self).increase_indent(flow, False)
foo = {
'instance_type': 'test',
'hostname': "\"testhost\"",
'name': 'foo',
'my_list': [
{'foo': 'test', 'bar': 'test2'},
{'foo': 'test3', 'bar': 'test4'}],
'hello': 'world',
}
print yaml.dump(foo, Dumper=MyDumper, default_flow_style=False)
输出:
hello: world
hostname: '"testhost"'
instance_type: test
my_list:
- bar: test2
foo: test
- bar: test4
foo: test3
name: foo
上面输出的主机名值有单引号和双引号,我只想要双引号。
预期输出:
hello: world
hostname: "testhost"
instance_type: test
my_list:
- bar: test2
foo: test
- bar: test4
foo: test3
name: foo
您得到的是双引号,因为这是您输入数据的内容。这一行:
'hostname': "\"testhost\"",
表示您希望 hosthame
具有一个以 "
开头和结尾的 10 个字符的字符串作为值,这就是您在 yaml 中看到的内容。这个带有转义双引号的字符串 "\"testhost\""
和 yaml 版本 '"testhost"'
是同一数据的两种不同的源代码表示形式。如果你想在其中嵌入特殊字符(如 \n
表示换行符),你只需要在 yaml 中的字符串周围加双引号。但是 yaml.dump()
会为您解决这个问题。
您不能通过引用部分数据来在 YAML 中强制引用。作为
引号强制转储程序对标量应用引号(即不能再
对于 yaml 文件中的其他字符串值使用普通标量)。
您需要制作一个带引号的转储类型。最容易的是
使用 ruamel.yaml
完成(免责声明:我是那个的作者
PyYAML增强版,支持YAML 1.2,支持往返
保留评论和引用等)。
import sys
import ruamel.yaml
from ruamel.yaml.scalarstring import DoubleQuotedScalarString as dq
yaml = ruamel.yaml.YAML()
yaml.indent(sequence=4, offset=2)
foo = {
'instance_type': 'test',
'hostname': dq("testhost"),
'name': 'foo',
'my_list': [
{'foo': 'test', 'bar': 'test2'},
{'foo': 'test3', 'bar': 'test4'}],
'hello': 'world',
}
yaml.dump(foo, sys.stdout)
给出:
instance_type: test
hostname: "testhost"
name: foo
my_list:
- foo: test
bar: test2
- foo: test3
bar: test4
hello: world
您还可以轻松加载该输出并将其转储以生成完全相同的输出:
from ruamel.yaml.compat import StringIO
buf = StringIO()
yaml.dump(foo, buf)
yaml.preserve_quotes = True
data = yaml.load(buf.getvalue())
yaml.dump(data, sys.stdout)
如果你坚持通过PyYAML来做,你可以声明你自己的强制引用类型并添加它的代表:
import yaml
class MyDumper(yaml.Dumper): # your force-indent dumper
def increase_indent(self, flow=False, indentless=False):
return super(MyDumper, self).increase_indent(flow, False)
class QuotedString(str): # just subclass the built-in str
pass
def quoted_scalar(dumper, data): # a representer to force quotations on scalars
return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='"')
# add the QuotedString custom type with a forced quotation representer to your dumper
MyDumper.add_representer(QuotedString, quoted_scalar)
foo = {
'instance_type': 'test',
'hostname': QuotedString('testhost'), # here's the 'magic'
'name': 'foo',
'my_list': [
{'foo': 'test', 'bar': 'test2'},
{'foo': 'test3', 'bar': 'test4'}],
'hello': 'world',
}
print(yaml.dump(foo, Dumper=MyDumper, default_flow_style=False))
哪个会给你:
hello: world
hostname: "testhost"
instance_type: test
my_list:
- bar: test2
foo: test
- bar: test4
foo: test3
name: foo
免责声明:如果可以选择,我也更喜欢 Anthon's ruamel.yaml
模块来满足我的 YAML 需求。
我在 Python 脚本中使用 yaml
模块生成 YAML 文件。下面是一个例子:
import yaml
class MyDumper(yaml.Dumper):
def increase_indent(self, flow=False, indentless=False):
return super(MyDumper, self).increase_indent(flow, False)
foo = {
'instance_type': 'test',
'hostname': "\"testhost\"",
'name': 'foo',
'my_list': [
{'foo': 'test', 'bar': 'test2'},
{'foo': 'test3', 'bar': 'test4'}],
'hello': 'world',
}
print yaml.dump(foo, Dumper=MyDumper, default_flow_style=False)
输出:
hello: world
hostname: '"testhost"'
instance_type: test
my_list:
- bar: test2
foo: test
- bar: test4
foo: test3
name: foo
上面输出的主机名值有单引号和双引号,我只想要双引号。
预期输出:
hello: world
hostname: "testhost"
instance_type: test
my_list:
- bar: test2
foo: test
- bar: test4
foo: test3
name: foo
您得到的是双引号,因为这是您输入数据的内容。这一行:
'hostname': "\"testhost\"",
表示您希望 hosthame
具有一个以 "
开头和结尾的 10 个字符的字符串作为值,这就是您在 yaml 中看到的内容。这个带有转义双引号的字符串 "\"testhost\""
和 yaml 版本 '"testhost"'
是同一数据的两种不同的源代码表示形式。如果你想在其中嵌入特殊字符(如 \n
表示换行符),你只需要在 yaml 中的字符串周围加双引号。但是 yaml.dump()
会为您解决这个问题。
您不能通过引用部分数据来在 YAML 中强制引用。作为 引号强制转储程序对标量应用引号(即不能再 对于 yaml 文件中的其他字符串值使用普通标量)。
您需要制作一个带引号的转储类型。最容易的是
使用 ruamel.yaml
完成(免责声明:我是那个的作者
PyYAML增强版,支持YAML 1.2,支持往返
保留评论和引用等)。
import sys
import ruamel.yaml
from ruamel.yaml.scalarstring import DoubleQuotedScalarString as dq
yaml = ruamel.yaml.YAML()
yaml.indent(sequence=4, offset=2)
foo = {
'instance_type': 'test',
'hostname': dq("testhost"),
'name': 'foo',
'my_list': [
{'foo': 'test', 'bar': 'test2'},
{'foo': 'test3', 'bar': 'test4'}],
'hello': 'world',
}
yaml.dump(foo, sys.stdout)
给出:
instance_type: test
hostname: "testhost"
name: foo
my_list:
- foo: test
bar: test2
- foo: test3
bar: test4
hello: world
您还可以轻松加载该输出并将其转储以生成完全相同的输出:
from ruamel.yaml.compat import StringIO
buf = StringIO()
yaml.dump(foo, buf)
yaml.preserve_quotes = True
data = yaml.load(buf.getvalue())
yaml.dump(data, sys.stdout)
如果你坚持通过PyYAML来做,你可以声明你自己的强制引用类型并添加它的代表:
import yaml
class MyDumper(yaml.Dumper): # your force-indent dumper
def increase_indent(self, flow=False, indentless=False):
return super(MyDumper, self).increase_indent(flow, False)
class QuotedString(str): # just subclass the built-in str
pass
def quoted_scalar(dumper, data): # a representer to force quotations on scalars
return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='"')
# add the QuotedString custom type with a forced quotation representer to your dumper
MyDumper.add_representer(QuotedString, quoted_scalar)
foo = {
'instance_type': 'test',
'hostname': QuotedString('testhost'), # here's the 'magic'
'name': 'foo',
'my_list': [
{'foo': 'test', 'bar': 'test2'},
{'foo': 'test3', 'bar': 'test4'}],
'hello': 'world',
}
print(yaml.dump(foo, Dumper=MyDumper, default_flow_style=False))
哪个会给你:
hello: world hostname: "testhost" instance_type: test my_list: - bar: test2 foo: test - bar: test4 foo: test3 name: foo
免责声明:如果可以选择,我也更喜欢 Anthon's ruamel.yaml
模块来满足我的 YAML 需求。