3

我正在尝试创建一个 yaml 格式,允许我在另一个对象中创建一个对象。在这个示例中,我试图创建一个状态机对象,同时用一些状态和它们之间的连接来填充它。

yaml.load("""
!statemachine {
     states: [
       !state { name: p1 },
       !state { name: p2 },
       !state { name: p3 },],
     connections:
      [!connection { 'pim' : [p1,p2]}]}
""")

!statemachine 有一个构造函数,它生成一个 MyStateMachine 类型的对象

!state 有一个构造函数,它生成一个 MyState 类型的对象

!connection 有一个构造函数,它应该使用以名称 p1 生成的对象并向其添加连接

我在这里有两个问题:

1 - 在创建状态机并且状态不存在于其中之后调用状态的构造函数

2 - 检索对象 p1 并在其上调用方法 add_connection。

提前致谢

4

2 回答 2

6

让我们尝试对象的真正pyyaml语法

myyaml.py:

import yaml,sys

class StateMachine(object):
    pass

class State(object):
    pass

class Connection(object):
    pass

if __name__ == '__main__':
    o = yaml.load("""
    !!python/object:myyaml.StateMachine {
         states: [
           !!python/object:myyaml.State { name: p1 },
           !!python/object:myyaml.State { name: p2 },
           !!python/object:myyaml.State { name: p3 },],
         connections:
          [       !!python/object:myyaml.Connection { 'pim' : [p1,p2]}]}
    """)
    print o.states[0].name
    print o.states[1].name
    print o.connections[0].pim
    sys.exit(0)

获取:

p1
p2
['p1', 'p2']

并且永远不要尝试模块根块中的 yaml.load() ,始终if __name__ == '__main__'在确保它会被调用一次的函数中使用或调用它。

请注意 yaml 声明:

!!python/object:myyaml.State { name: p1 },

此时 yaml 尝试在另一个上下文中再次导入 myyaml.py,并且模块根目录中的所有代码都将被执行,如果您将 yaml.load 或类似的东西放在模块根目录中,您可能会遇到无限循环,或者意外的结果。

于 2013-06-19T13:10:09.177 回答
2

为了补充pylover 的回答:如果在某些时候您需要对序列化/反序列化过程进行更多控制,请尝试yamlable。我为我们的一些生产代码编写了这个包,以便对 yaml 到对象的绑定有更多的控制。

在您的示例中:

import yaml
import sys
from yamlable import YamlAble, yaml_info


@yaml_info(yaml_tag_ns='myyaml')
class StateMachine(YamlAble):

    def __init__(self, states, connections):
        self.states = states
        self.connections = connections

    # def to_yaml_dict(self):
    #     return vars(self)
    #
    # @classmethod
    # def from_yaml_dict(cls, dct, yaml_tag):
    #     return StateMachine(**dct)


@yaml_info(yaml_tag_ns='myyaml')
class State(YamlAble):

    def __init__(self, name):
        self.name = name

    # def to_yaml_dict(self):
    #     return vars(self)
    #
    # @classmethod
    # def from_yaml_dict(cls, dct, yaml_tag):
    #     return State(**dct)


@yaml_info(yaml_tag_ns='myyaml')
class Connection(YamlAble):

    def __init__(self, pim):
        self.pim = pim

    # def to_yaml_dict(self):
    #     return vars(self)
    #
    # @classmethod
    # def from_yaml_dict(cls, dct, yaml_tag):
    #     return Connection(**dct)


if __name__ == '__main__':
    o = yaml.safe_load("""
    !yamlable/myyaml.StateMachine {
         states: [
           !yamlable/myyaml.State { name: p1 },
           !yamlable/myyaml.State { name: p2 },
           !yamlable/myyaml.State { name: p3 },],
         connections:
          [       !yamlable/myyaml.Connection { 'pim' : [p1,p2]}]}
    """)
    print(o.states[0].name)
    print(o.states[1].name)
    print(o.connections[0].pim)

    print(yaml.safe_dump(o))

    # Note: these also work
    # print(o.loads_yaml(""" ... """))
    # print(o.dumps_yaml())

    sys.exit(0)

如果您需要更改默认行为,例如仅转储某些字段,或更改其结构以进行转储,或在加载时执行一些自定义实例创建,请取消注释相应的方法。

有关更多详细信息,请参阅yamlable 文档

于 2018-07-10T08:41:40.003 回答