3ya*_*uya 3 python yaml pyyaml
当我使用PyYAML在Python中编辑YAML文件时,我所有的字符串值都保存回没有引号的原始文件中。
one: valueOne
two: valueTwo
three: valueThree
Run Code Online (Sandbox Code Playgroud)
我希望这些字符串之一用单引号引起来:
one: valueOne
two: valueTwo
three: 'valueThree'
Run Code Online (Sandbox Code Playgroud)
更改中的default_style参数yaml_dump会影响整个文件,这是不希望的。我考虑过在要包围的字符串的开头和结尾添加单引号:
valueThreeVariable = "'" + valueThreeVariable + "'"
Run Code Online (Sandbox Code Playgroud)
但是,最终会得到如下所示的转储YAML:
one: valueOne
two: valueTwo
three: '''valueThree'''
Run Code Online (Sandbox Code Playgroud)
我尝试使用unicode或原始字符串以各种方式转义单引号,但都无济于事。如何仅使我的YAML值之一成为用单引号引起来的字符串?
您可以将此类功能嫁接到PyYAML上,但这并不容易。映射中的值three必须是与普通字符串不同的类的某个实例,否则YAML转储器不知道它必须做一些特殊的事情,并且该实例将作为带引号的字符串转储。在加载带有单引号的标量时,需要将其创建为此类的实例。除此之外,您可能不希望您的dict/ 密钥mapping像PyYAML默认那样被打乱。
对于块样式标量,我在PyYAML派生的ruamel.yaml中执行与上面类似的操作:
import ruamel.yaml
yaml_str = """\
one: valueOne
two: valueTwo
three: |-
valueThree
"""
data = ruamel.yaml.round_trip_load(yaml_str)
assert ruamel.yaml.round_trip_dump(data) == yaml_str
Run Code Online (Sandbox Code Playgroud)
不会引发断言错误。
要开始使用转储程序,您可以“转换” valueThree字符串:
import ruamel.yaml
from ruamel.yaml.scalarstring import ScalarString
yaml_str = """\
one: valueOne
two: valueTwo
three: 'valueThree'
"""
class SingleQuotedScalarString(ScalarString):
def __new__(cls, value):
return ScalarString.__new__(cls, value)
data = ruamel.yaml.round_trip_load(yaml_str)
data['three'] = SingleQuotedScalarString(data['three'])
Run Code Online (Sandbox Code Playgroud)
但这不能转储,因为转储者不了解SingleQuotedScalarString。您可以解决以不同的方式,下面扩展ruamel.yaml的RoundTripRepresenter类:
from ruamel.yaml.representer import RoundTripRepresenter
import sys
def _represent_single_quoted_scalarstring(self, data):
tag = None
style = "'"
if sys.version_info < (3,) and not isinstance(data, unicode):
data = unicode(data, 'ascii')
tag = u'tag:yaml.org,2002:str'
return self.represent_scalar(tag, data, style=style)
RoundTripRepresenter.add_representer(
SingleQuotedScalarString,
_represent_single_quoted_scalarstring)
assert ruamel.yaml.round_trip_dump(data) == yaml_str
Run Code Online (Sandbox Code Playgroud)
再一次不会引发错误。以上可以在PyYAML和safe_load/ safe_dump原则上完成,但是您将需要编写代码来保留键顺序以及一些基本功能。(除此之外,PyYAML仅支持较早的YAML 1.1标准,而不支持2009年以来的YAML 1.2标准)。
为了使加载工作不使用显式data['three'] = SingleQuotedScalarString(data['three'])转换,可以在调用之前添加以下内容ruamel.yaml.round_trip_load():
from ruamel.yaml.constructor import RoundTripConstructor
from ruamel.yaml.nodes import ScalarNode
from ruamel.yaml.compat import text_type
def _construct_scalar(self, node):
if not isinstance(node, ScalarNode):
raise ConstructorError(
None, None,
"expected a scalar node, but found %s" % node.id,
node.start_mark)
if node.style == '|' and isinstance(node.value, text_type):
return PreservedScalarString(node.value)
elif node.style == "'" and isinstance(node.value, text_type):
return SingleQuotedScalarString(node.value)
return node.value
RoundTripConstructor.construct_scalar = _construct_scalar
Run Code Online (Sandbox Code Playgroud)
有多种方法可以执行上述操作,包括对RoundTripConstructor类进行子类化,但是更改的实际方法很小,可以轻松进行修补。
结合以上所有内容并进行一些清理,您将得到:
import ruamel.yaml
from ruamel.yaml.scalarstring import ScalarString
from ruamel.yaml.representer import RoundTripRepresenter
from ruamel.yaml.constructor import RoundTripConstructor
from ruamel.yaml.nodes import ScalarNode
from ruamel.yaml.compat import text_type, PY2
class SingleQuotedScalarString(ScalarString):
def __new__(cls, value):
return ScalarString.__new__(cls, value)
def _construct_scalar(self, node):
if not isinstance(node, ScalarNode):
raise ConstructorError(
None, None,
"expected a scalar node, but found %s" % node.id,
node.start_mark)
if node.style == '|' and isinstance(node.value, text_type):
return PreservedScalarString(node.value)
elif node.style == "'" and isinstance(node.value, text_type):
return SingleQuotedScalarString(node.value)
return node.value
RoundTripConstructor.construct_scalar = _construct_scalar
def _represent_single_quoted_scalarstring(self, data):
tag = None
style = "'"
if PY2 and not isinstance(data, unicode):
data = unicode(data, 'ascii')
tag = u'tag:yaml.org,2002:str'
return self.represent_scalar(tag, data, style=style)
RoundTripRepresenter.add_representer(
SingleQuotedScalarString,
_represent_single_quoted_scalarstring)
yaml_str = """\
one: valueOne
two: valueTwo
three: 'valueThree'
"""
data = ruamel.yaml.round_trip_load(yaml_str)
assert ruamel.yaml.round_trip_dump(data) == yaml_str
Run Code Online (Sandbox Code Playgroud)
仍然运行而没有断言错误,即转储输出等于输入。如前所述,您可以在PyYAML中执行此操作,但是它需要更多的编码。
使用更现代的版本(ruamel.yaml> 0.14),您可以执行以下操作:
yaml = ruamel.yaml.YAML()
yaml.preserve_quotes = True
data = yaml.load(yaml_str)
yaml.dump(data, sys.stdout)
Run Code Online (Sandbox Code Playgroud)
并保留单引号。
| 归档时间: |
|
| 查看次数: |
1732 次 |
| 最近记录: |