lib python python-3.x yaml pyyaml

python - lib - yaml c



Formato de volcado de PyYAML (3)

En mi caso, quiero " si el valor contiene un { o un } , de lo contrario nada. Por ejemplo:

en: key1: value is 1 key2: ''value is {1}''

Para realizar eso, copie la función represent_str() del archivo representer.py en el módulo PyYaml y use otro estilo si la cadena contiene { o a } :

def represent_str(self, data): tag = None style = None # Add these two lines: if ''{'' in data or ''}'' in data: style = ''"'' try: data = unicode(data, ''ascii'') tag = u''tag:yaml.org,2002:str'' except UnicodeDecodeError: try: data = unicode(data, ''utf-8'') tag = u''tag:yaml.org,2002:str'' except UnicodeDecodeError: data = data.encode(''base64'') tag = u''tag:yaml.org,2002:binary'' style = ''|'' return self.represent_scalar(tag, data, style=style)

Para usarlo en tu código:

import yaml def represent_str(self, data): ... yaml.add_representer(str, represent_str)

En este caso, no hay diferencias entre claves y valores y eso es suficiente para mí. Si desea un estilo diferente para claves y valores, realice lo mismo con la función represent_mapping

Sé que hay algunas preguntas sobre esto en SO, pero no pude encontrar lo que estaba buscando.

Estoy usando pyyaml para leer ( .load() ) un archivo .yml , modificar o agregar una clave y luego escribirla ( .dump() ) nuevamente. El problema es que quiero mantener el formato de archivo post-dump, pero cambia.

Por ejemplo, edito la clave en.test.index.few para decir "Bye" lugar de "Hello"

Pitón:

with open(path, ''r'', encoding = "utf-8") as yaml_file: self.dict = pyyaml.load(yaml_file)

Luego, después de cambiar la llave:

with open(path, ''w'', encoding = "utf-8") as yaml_file: dump = pyyaml.dump(self.dict, default_flow_style = False, allow_unicode = True, encoding = None) yaml_file.write( dump )

Yaml:

Antes de:

en: test: new: "Bye" index: few: "Hello" anothertest: "Something"

Después:

en: anothertest: Something test: index: few: Hello new: Bye

¿Hay alguna manera de mantener el mismo formato ?, por ejemplo, las preguntas y el orden. ¿Estoy usando la herramienta incorrecta para esto?

Sé que tal vez el archivo original no sea del todo correcto, pero no tengo control sobre él (es un archivo Ruby on Rails i18n).

Muchas gracias.


Utilice ruamel.yaml en ruamel.yaml lugar.

¡Lucha de biblioteca! Un cuento de dos bibliotecas

PyYAML está efectivamente muerto y lo ha estado durante varios años. Para agravar las cuestiones, la página oficial del proyecto en pyyaml parece haber sido eliminada recientemente. Este sitio albergaba el rastreador, la documentación y las descargas de problemas de PyYAML. A partir de este escrito, todos se han ido. Esto es nada menos que calamitoso. Bienvenidos a un día más en código abierto.

ruamel.yaml se mantiene activamente . A diferencia de PyYAML, ruamel.yaml admite:

  • YAML <= 1.2. PyYAML solo admite YAML <= 1.1. Esto es vital, ya que YAML 1.2 intencionalmente rompe la compatibilidad con YAML 1.1 en varios casos de borde. Esto usualmente sería una mala cosa. En este caso, esto hace que YAML 1.2 sea un superconjunto estricto de JSON. Ya que YAML 1.1 no es un superconjunto estricto de JSON, esto es algo bueno.
  • Conservación de ida y vuelta. Al llamar a yaml.dump() para volcar un diccionario cargado por una llamada previa a yaml.load() :
    • PyYAML ignora ingenuamente todo el formato de entrada, incluidos los comentarios, los pedidos, las citas y los espacios en blanco. Desechado como tanta basura digital en el cubo de bits disponible más cercano.
    • ruamel.yaml respeta inteligentemente todo el formato de entrada. Todo. Toda la enchilada estilística. Todo el shebang literario. Todos.

Migración de la biblioteca: El sendero de Code Tears

Como ruamel.yaml es una bifurcación de PyYAML y, por lo tanto, se ajusta a la API de PyYAML, el cambio de PyYAML a ruamel.yaml en las aplicaciones existentes suele ser tan simple como reemplazar todas las instancias de esto:

# This imports PyYAML. Stop doing this. import yaml

...con este:

# This imports "ruamel.yaml". Always do this. from ruamel import yaml

Eso es.

No deberían ser necesarios otros cambios. Las yaml.load() y yaml.dump() deben seguir comportándose como se espera, con los beneficios adicionales de ser compatible con YAML 1.2 y recibir correcciones de errores de forma activa.

Preservación de ida y vuelta y lo que puede hacer por usted

Para la compatibilidad con versiones anteriores de PyYaml, las yaml.load() y yaml.dump() no realizan la conservación de ida y vuelta de forma predeterminada. Para hacerlo, explícitamente pasar:

  • El parámetro opcional Loader=ruamel.yaml.RoundTripLoader para yaml.load() .
  • El parámetro de palabra clave opcional Dumper=ruamel.yaml.RoundTripDumper para yaml.dump() .

Un ejemplo amablemente "tomado prestado" de la documentación de ruamel.yaml :

import ruamel.yaml inp = """/ # example name: # Yet another Great Duke of Hell. He''s not so bad, really. family: TheMighty given: Ashtaroth """ code = ruamel.yaml.load(inp, Loader=ruamel.yaml.RoundTripLoader) code[''name''][''given''] = ''Astarte'' # Oh no you didn''t. print(ruamel.yaml.dump(code, Dumper=ruamel.yaml.RoundTripDumper), end='''')

Se hace. Los comentarios, los pedidos, las citas y los espacios en blanco se conservarán intactos.

tl; dr

Siempre use ruamel.yaml . Nunca uses PyYAML. ruamel.yaml vive. PyYAML es un cadáver fétido que se pudre en el moleteado suelo de PyPi.

Larga vida a ruamel.yaml .


primero

Para representar los datos del diccionario se utiliza el siguiente código:

mapping = list(mapping.items()) try: mapping = sorted(mapping) except TypeError: pass

Es por eso que se cambia el pedido.

Segundo

La información sobre cómo se presentó el tipo escalar (con comillas dobles o no) se pierde al leer (este es el enfoque principal de la biblioteca)

Resumen

Puede crear su propia clase basada en ''Dumper'' y al método de sobrecarga ''represent_mapping'' para cambiar el comportamiento de cómo se presentará el diccionario.

Para guardar información sobre las comillas dobles para escalar, también debe crear una clase propia basada en ''Loader'', pero me temo que afectará a otras clases y que será difícil hacerlo.