Guardar/volcar un archivo YAML con comentarios en PyYAML

3 minutos de lectura

Tengo un archivo yaml que se ve así:

# The following key opens a door
key: value

¿Hay alguna manera de que pueda load y dump estos datos manteniendo el comentario?

  • Una vez modifiqué el código C libyaml para emitir comentarios para mi propio uso. Extender esto a PyYAML no va a ser fácil.

    –David Heffernan

    31 de agosto de 2011 a las 16:37


  • Volví a pensar en esto. ¿Tiene sentido analizar y escribir un archivo yaml que se editó a mano (y se editará a mano en el futuro)? ¿Por qué no dividir el archivo en dos partes? Una está hecha a mano y la otra parte son datos puros (sin comentarios). Relacionado: github.com/guettli/programming-guidelines/blob/master/…

    – Guettli

    16 de septiembre de 2019 a las 8:02

Avatar de usuario de Anthon
Antonio

Si usa YAML estructurado en bloques, puede usar el paquete python¹ ruamel.yaml que es un derivado de PyYAML y admite la conservación de comentarios de ida y vuelta:

import sys
import ruamel.yaml

yaml_str = """\
# example
name:
  # details
  family: Smith   # very common
  given: Alice    # one of the siblings
"""

yaml = ruamel.yaml.YAML()  # defaults to round-trip if no parameters given
code = yaml.load(yaml_str)
code['name']['given'] = 'Bob'

yaml.dump(code, sys.stdout)

con resultado:

# example
name:
  # details
  family: Smith   # very common
  given: Bob      # one of the siblings

Tenga en cuenta que los comentarios al final de la línea todavía están alineados.

en lugar de normal list y dict objeta el code consta de versiones envueltas² en las que se adjuntan los comentarios.

¹ Instalar con pip install ruamel.yaml. Funciona en Python 2.6/2.7/3.3+

² ordereddict se utiliza en el caso de un mapeo, para preservar el orden

  • Esto no responde a la pregunta de OP. Conserva el orden, pero no los comentarios.

    – Cerín

    22 de enero de 2017 a las 22:58

  • @cerin ¿Qué comentarios faltan cuando ejecuta el código anterior? ¿Con qué versión de Python, ruamel.yaml y en qué plataforma ejecutó este código? Acabo de volver a intentar esto con la última versión de ruamel.yaml (en caso de que rompa algo) y el resultado aún incluye comentarios. Dada la cantidad de votos a favor aquí, creo que otros han podido obtener el mismo resultado y es posible que haya pasado por alto algo.

    – Antonio

    23 de enero de 2017 a las 6:35


  • @Anthon, parece ser inconsistente. En su ejemplo, los comentarios se conservan, pero en archivos yaml más complicados que probé, elimina algunos comentarios, especialmente si edita datos cerca de esos comentarios. Estoy usando la versión más reciente del paquete con Python 2.7.

    – Cerín

    24 de enero de 2017 a las 15:22

  • @cerin El viaje de ida y vuelta originalmente estaba allí para actualizar los valores en un archivo de configuración, eso siempre debería funcionar. La forma en que se “conservan” las cosas, si comienza a eliminar claves, los comentarios podrían desaparecer. Preferiría que hiciera una pregunta al respecto en Stack Overflow o presentara un informe de error. Tiendo a arreglar las cosas si puedo y trato de dar soluciones alternativas, o al menos una explicación si no puedo.

    – Antonio

    24 de enero de 2017 a las 19:27

  • Si alguien quiere un formato YAML más estándar, puede usar yaml.indent(mapping=2, sequence=4, offset=2) antes de hacer dump

    – El Padrino

    1 de abril de 2020 a las 9:34


avatar de usuario de phihag
phihag

PyYAML desecha los comentarios a un nivel muy bajo (en Scanner.scan_to_next_token).

Si bien podría adaptarlo o extenderlo para manejar comentarios en toda su pila, esta sería una modificación importante. Dumpenviar (=emitir) comentarios parece ser más fácil y se discutió en boleto 114 en el antiguo rastreador de errores de PyYAML.

A partir de 2023, el solicitud de función sobre agregar soporte para cargar comentarios todavía está estancado.

  • Tiene razón, fue una modificación importante, aunque más fácil porque eliminé el soporte

    – Antonio

    24/11/2014 a las 11:00

Tengo una rama de pyyaml ​​que hace exactamente esto.
https://github.com/pflarr/pyyaml

Para crear un archivo yaml con comentarios, debe crear un flujo de eventos que incluya eventos de comentarios. Actualmente, los comentarios solo se permiten antes de los elementos de secuencia y las claves de asignación.

Actualmente, esto solo funciona para python3, no lo he portado a la versión python2 de la biblioteca, pero podría hacerlo fácilmente a pedido. Además, esto también debería ser bastante fácil de portar a C libyaml, ya que el código python es un puerto simple de todos modos.

Si no está limitado por un esquema de archivo, puede elegir un patrón de clave específico para que signifique “entrada ignorada”. Por ejemplo, su lógica de ingestión de datos yaml puede filtrar cualquier entrada con una clave que comience con ‘~’ :

company:
  ~name: Must be the legal name
  name: Curious Adventures
  ~address: the official correspondence address
  address: 1234, New York, PO 1234

He usado este enfoque para archivos JSON ya que tenemos el mismo problema con los comentarios.

¿Ha sido útil esta solución?