Disabling alias for yaml file in python

穿精又带淫゛_ 提交于 2021-01-27 18:25:03

问题


I have a problem that I wish to prevent aliases from occurring in my YAML file. Is there anyway I can disable the aliases in the YAML file generated, to achieve the intended output?

The current YAML file I have is this below:

agents:
-   start: [0, 0]
    goal: [2, 0]
    name: agent0
-   start: [2, 0]
    goal: [0, 0]
    name: agent1
map:
    dimensions: [3, 3]
    obstacles:
    - !!python/tuple [0, 1]
    - !!python/tuple [2, 1]

As I updating the YAML file for each of the agents whenever they reached their goal point with the value of the goal to the start, I will encounter this problem of alias being the value of the start and goal value instead of the value I want, i.e. [0,0] for start, [0,0] for goal.

agents:
- start: &id001 [2, 0]
  goal: *id001
  name: agent0
- start: &id002 [0, 0]
  goal: *id002
  name: agent1
map:
  dimensions: [3, 3]
  obstacles:
  - !!python/tuple [0, 1]
  - !!python/tuple [2, 1]

Intended output:

agents:
- start: [2, 0]
  goal: [2, 0]
  name: agent0
- start: [0, 0]
  goal: [0, 0]
  name: agent1
map:
  dimensions: [3, 3]
  obstacles:
  - !!python/tuple [0, 1]
  - !!python/tuple [2, 1]

I have following code that I run in Python to update the file:

def updateInput(self, agent):
        yaml = ruamel.yaml.YAML()
        with open('input.yaml') as f:
            doc = yaml.load(f)
            self.get_updated_dict(doc, agent)

        with open('input.yaml', 'w') as y:
            yaml.dump(doc, y)

        return {}
    def get_updated_dict(self, doc, agent):
        obj = doc
        if obj["agents"][0]["name"] == agent:
            goal_state = obj["agents"][0]["goal"]
            obj["agents"][0]["start"] = goal_state   
        return doc

回答1:


The representer stage of ruamel.yaml creates the aliases, but for every piece of data it checks with the ignore_aliases method (defaulting to False) whether the aliases should be ignored for that piece of data.

In the following I suppress all aliases, but you can make this dependent on the (type of) data that is being represented. (This just shows the principle, you don't first have to write the YAML version with aliases, just add the line

yaml.representer.ignore_aliases = lambda *data: True

anywhere after instantiation yaml)

import sys
import ruamel.yaml

yaml_str = """\
agents:
- start: &id001 [2, 0]
  goal: *id001
  name: agent0
- start: &id002 [0, 0]
  goal: *id002
  name: agent1
map:
  dimensions: [3, 3]
  obstacles:
  - !!python/tuple [0, 1]
  - !!python/tuple [2, 1]
"""

yaml = ruamel.yaml.YAML()
yaml.representer.ignore_aliases = lambda *data: True
data = yaml.load(yaml_str)
yaml.dump(data, sys.stdout)

which gives:

agents:
- start: [2, 0]
  goal: [2, 0]
  name: agent0
- start: [0, 0]
  goal: [0, 0]
  name: agent1
map:
  dimensions: [3, 3]
  obstacles:
  - !!python/tuple [0, 1]
  - !!python/tuple [2, 1]

Take care though that if you have self-recursing data, you're going to have to wait a long time until your file gets written (depending of course on your disc-capacity).



来源:https://stackoverflow.com/questions/58091449/disabling-alias-for-yaml-file-in-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!