Utiliser des balises personnalisées avec PyYAML

Quand j'ai cherché, il n'y avait pas d'échantillons (même dans les pays anglophones!), Donc c'était facile.

Déclencheur

J'écrivais du code en Python qui définit le comportement d'un programme en YAML, et je voulais juste écrire un processus pour créer un objet en YAML.

Pour autant que je puisse voir PyYAMLDocumentation, il y a une ** balise **, qui semble faire ce que je veux, mais il n'y a aucun exemple d'utilisation nulle part. Je ne sais pas s'il doit être utilisé ni comment le définir. Eh bien, j'étais en difficulté.

Comment ajouter une balise

Alors, du coup, c'est le sujet principal. Pour ajouter une balise, transmettez une valeur à la fonction globale du module PyYAML, ʻadd_multi_constructor () `.

  yaml.add_multi_constructor("tag:yaml.org,2002:var", var_handler)

  # ...

  def var_handler(loader, suffix, node=None):
    #En traitement

Si vous écrivez un tel code, il réagira lorsque le fichier YAML aura la balise suivante et var_handler sera appelé.

  textvariable: !!var:StringVar
    name: label
    default: ""

Trois paramètres sont passés à la fonction spécifiée dans l'argument

Ainsi, si vous renvoyez une valeur comme valeur de retour de la fonction, la partie balise sera la valeur spécifiée pour la valeur de retour. Par exemple, dans l'exemple ci-dessus, renvoyer le mot «Oui» équivaut à écrire «textvariable: Yes».

ʻAdd_multi_constructor () `Si vous suivez le comportement de la fonction, si vous omettez le Loader défini comme argument de mot-clé, la fonction spécifiée ici semble être ajoutée aux trois classes Loader, FullLoader et UnsafeLoader. Donc, si vous utilisez SafeLoader **, peu importe ce que vous faites ici, aucune fonction ne sera ajoutée. ** **

Si vous souhaitez utiliser uniquement les balises que vous avez définies dans YAML

Lors du chargement de YAML, si vous souhaitez charger uniquement les balises que vous avez définies vous-même, vous pouvez ajouter une fonction en spécifiant SafeLoader comme argument.

J'avais un autre processus et je me sentais un peu inquiet de jouer directement avec SafeLoader, alors j'ai défini une nouvelle classe qui a hérité de SafeLoader.

class GeneratorLoader(yaml.SafeLoader):
  def __init__(self, stream):
    super().__init__(stream)
    yaml.add_multi_constructor("tag:yaml.org,2002:var", GeneratorLoader.var_handler,
      Loader=GeneratorLoader)

  @staticmethod
  def var_handler(loader, suffix, node=None):
    pass

Si vous utilisez la classe créée ici comme Loader dans la méthode yaml.load (), les balises seront traitées.

Les fonctions globales PyYAML n'ont pas de fonction qui reçoit une instance de Loader

Notez que les fonctions définies dans \ _ \ _ init \ _ \ _. Py de PyYAML telles que yaml.load () n'ont pas de fonction qui reçoit une instance de Loader (toutes reçoivent des classes). Par conséquent, si vous souhaitez utiliser l'objet Loader créé ci-dessus après le chargement de YAML, vous devez appeler Loader # get_single_data () directement.

loader = GeneratorLoader(self.string)
struct = loader.get_single_data()

Autres notes

Je ne comprends pas l'explication, alors montrez-moi le code pour le moment

Je travaille dessus maintenant, mais je l'utilise dans le module suivant.

Depuis le 21 septembre 2020, il existe un tel processus dans tksugar / generator.py (peut déplacer le code plus tard).

Les références

Recommended Posts

Utiliser des balises personnalisées avec PyYAML
Utiliser un noyau personnalisé avec WSL2
Utilisez RTX 3090 avec PyTorch
Utiliser ansible avec cygwin
Utiliser pipdeptree avec virtualenv
[Python] Utiliser JSON avec Python
Utilisez Mock avec pytest
Utiliser l'indicateur avec pd.merge
Utiliser Gentelella avec Django
Utiliser mecab avec Python 3
Utiliser tensorboard avec Chainer
Utiliser DynamoDB avec Python
Utiliser pip avec MSYS2
Utilisez Python 3.8 avec Anaconda
Utiliser les droits d'auteur avec Spacemacs
Utiliser python avec docker
Utiliser TypeScript avec django-compresseur
Utilisez LESS avec Django
Utiliser MySQL avec Django
Utiliser Enum avec SQLAlchemy
Utiliser tensorboard avec NNabla
Utiliser le GPS avec Edison
Utilisez nim avec Jupyter
Utiliser l'API Trello avec python
Utiliser la mémoire partagée avec une bibliothèque partagée
Utiliser des graphiques directionnels avec networkx
Utiliser TensorFlow avec Intellij IDEA
Utiliser l'API Twitter avec Python
Utiliser pip avec Jupyter Notebook
Utiliser DATE_FORMAT avec le filtre SQLAlchemy
Utiliser TUN / TAP avec Python
Utilisez sqlite3 avec NAO (Pepper)
Utilisez les load_extensions de sqlite avec Pyramid
Utiliser les polices Windows 10 avec WSL
Utilisation du chainer avec Jetson TK1
Utiliser SSL avec Celery + Redis
Utiliser Cython avec Jupyter Notebook
Créez des règles personnalisées avec ElastAlert
Utilisez Maxout + CNN avec Pylearn2
Utilisez WDC-433SU2M2 avec Manjaro Linux
Utilisez OpenBLAS avec numpy, scipy
Utiliser l'API subsonique avec python3
Utilisation de Sonicwall NetExtener avec Systemd
Utilisez prefetch_related commodément avec Django
Utiliser l'interpréteur AWS avec Pycharm
Utilisation de Bokeh avec IPython Notebook
Utiliser une plage de type Python avec Rust
Utiliser MLflow avec Databricks ④ --Call model -
Python: comment utiliser async avec
Utiliser la caméra Point Grey avec Python (PyCapture2)
Utilisez vl53l0x avec RaspberryPi (python)
Utilisez PX-S1UD / PX-Q1UD avec Jetson nano
Utilisez la fonction de prévisualisation avec aws-cli
Pour utiliser virtualenv avec PowerShell
Utilisez NAIF SPICE TOOL KIT avec Python
Utiliser rospy avec virtualenv dans Python3
Utilisez des scripts personnalisés Python avec StackStorm
Utiliser Markdown avec le notebook Jupyter (avec raccourci)