Vous pouvez greffer une telle fonctionnalité sur PyYAML mais ce n'est pas facile. La valeur dans le mappage pour three
doit être une instance d'une classe différente d'une chaîne normale, sinon le dumper YAML ne sait pas qu'il doit faire quelque chose de spécial et cette instance est sauvegardée sous forme de chaîne avec des guillemets. Lors du chargement de scalaires avec des guillemets simples doivent être créés en tant qu'instances de cette classe. Et à part ça, vous ne voulez probablement pas que les clés de votre dict
/mapping
soient brouillées comme le fait PyYAML par défaut.
je fais quelque chose de similaire à ce qui précède dans mon dérivé PyYAML ruamel.yaml pour le style bloc scalaires:
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
ne jette pas une erreur d'assertion.
Pour commencer par le dumper, vous pouvez « convertir » la chaîne 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'])
mais cela ne peut pas être sous-évaluées, comme le dumper ne connaît pas le SingleQuotedScalarString
. Vous pouvez résoudre ce de différentes manières, ce qui suit étend la classe de RoundTripRepresenter
ruamel.yaml
:
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
Encore une fois ne jette pas une erreur. Ce qui précède peut être fait dans PyYAML et le safe_load
/safe_dump
en principe, mais vous auriez besoin d'écrire du code pour préserver l'ordre des clés, ainsi que certaines fonctionnalités de base. (En dehors de cela, PYYAML ne supporte que l'ancienne norme YAML 1.1 et non la norme YAML 1.2 de 2009).
Pour obtenir le chargement de travailler sans utiliser la conversion data['three'] = SingleQuotedScalarString(data['three'])
explicite, vous pouvez ajouter ce qui suit avant l'appel à 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
Il existe différentes façons de le faire ci-dessus, y compris le sous-classement de la classe RoundTripConstructor
, mais la méthode de changement est petite et peut facilement être corrigée.
La combinaison de ce qui précède et nettoyer un peu, vous obtenez:
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
qui fonctionne toujours sans erreur d'assertion, à savoir avec une sortie de décharge d'entrée égal. Comme indiqué, vous pouvez le faire dans PyYAML, mais cela nécessite beaucoup plus de codage.
Avec une version plus moderne (ruamel.yaml> 0.14) vous pouvez faire:
yaml = ruamel.yaml.YAML()
yaml.preserve_quotes = True
data = yaml.load(yaml_str)
yaml.dump(data, sys.stdout)
et de préserver les guillemets simples.
Pourquoi voulez-vous faire cela? –
Voici quelque chose à essayer. Je ne sais pas si ça va marcher - je n'ai jamais utilisé PyYaml. Essayez ceci: valueThreeVariable = "'{0}'" .format (valueThreeVariable). Notez les espaces à l'intérieur des guillemets autour des guillemets simples. –
@TomBarron malheureusement, cela formate la chaîne unique dans ''' 'StringHere' ''' façon – 3yakuya