[PYTHON] Use custom tags with PyYAML

When I looked it up, there weren't any samples (even in English-speaking countries!), So it was easy.

Trigger

I was writing code in Python that defines the behavior of a program in YAML, and I just wanted to write a process to create an object in YAML.

As far as I can see PyYAMLDocumentation, there is a ** tag **, which seems to do what I want, but there is no usage example anywhere. I don't know if it should be used or how to define it. Well I was in trouble.

How to add a tag

So, suddenly it's the main subject. To add a tag, pass a value to the PyYAML module's global function, ʻadd_multi_constructor () `.

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

  # ...

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

If you write such code, it will react when the YAML file has the following tag and var_handler will be called.

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

Three parameters are passed to the function specified as an argument

So, if you return some value as the return value of the function, the tag part will be the value specified in the return value. For example, in the above example, returning the character "Yes" is the same as writing textvariable: Yes.

ʻAdd_multi_constructor ()` If you follow the behavior of the function, it seems that if you omit the Loader defined as a keyword argument, the function specified here will be added to the three classes Loader, FullLoader, and UnsafeLoader. So if you use SafeLoader ** no matter what you do here, no function will be added. ** **

If you want to use only tags that you have defined in YAML

When reading YAML, if you want to read only the tags defined by yourself, it is better to specify SafeLoader as an argument and add a function.

I had some other work to do, and I was a little worried about messing with SafeLoader directly, so I defined a new class that inherited 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

If you use the class created here as a Loader in the yaml.load () method, the tags will be processed.

Global functions in PyYAML do not have a function that receives an instance of Loader

Note that the functions defined in \ _ \ _ init \ _ \ _. Py of PyYAML such as yaml.load () do not have a function that receives an instance of Loader (all receive classes). Therefore, if you want to use the Loader object created above after loading YAML, you need to call Loader # get_single_data () directly.

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

Other notes

I don't understand the explanation, so show me the code for the time being

I'm working on it now, but I'm using it in the next module.

As of September 21, 2020, there is such a process in tksugar / generator.py (may move the code later).

References

Recommended Posts

Use custom tags with PyYAML
Use a custom kernel with WSL2
Use RTX 3090 with PyTorch
Use ansible with cygwin
Use pipdeptree with virtualenv
[Python] Use JSON with Python
Use Mock with pytest
Use indicator with pd.merge
Use Gentelella with django
Use mecab with Python3
Use tensorboard with Chainer
Merge array with PyYAML
Use DynamoDB with Python
Use pip with MSYS2
Use Python 3.8 with Anaconda
Use pyright with Spacemacs
Use python with docker
Use TypeScript with django-compressor
Use LESS with Django
Use MySQL with Django
Use Enums with SQLAlchemy
Use tensorboard with NNabla
Use GPS with Edison
Use nim with Jupyter
Use Trello API with python
Use shared memory with shared libraries
Use "$ in" operator with mongo-go-driver
Use directional graphs with networkx
Use TensorFlow with Intellij IDEA
Use Twitter API with Python
Use pip with Jupyter Notebook
Use DATE_FORMAT with SQLAlchemy filter
Use TUN / TAP with Python
Use sqlite3 with NAO (Pepper)
Use sqlite load_extensions with Pyramid
Use Windows 10 fonts with WSL
Use chainer with Jetson TK1
Use SSL with Celery + Redis
Use Cython with Jupyter Notebook
Create custom rules with ElastAlert
Use Maxout + CNN with Pylearn2
Use WDC-433SU2M2 with Manjaro Linux
Use OpenBLAS with numpy, scipy
Use subsonic API with python3
Use Sonicwall NetExtener with Systemd
Use prefetch_related conveniently with Django
Use AWS interpreter with Pycharm
Use Bokeh with IPython Notebook
Use Python-like range with Rust
Use MLflow with Databricks ④ --Call model -
Python: How to use async with
Use PointGrey camera with Python (PyCapture2)
Use vl53l0x with Raspberry Pi (python)
Use PX-S1UD / PX-Q1UD with Jetson nano
Use the preview feature with aws-cli
How to use virtualenv with PowerShell
[Python] Use Basic/Digest authentication with Flask
Use NAIF SPICE TOOLKIT with Python
Use rospy with virtualenv in Python3
Utilize Python custom scripts with StackStorm
Use markdown with jupyter notebook (with shortcut)