Graphviz——实现动态更新协议状态机

1、描述

2、实现

  • 在fsm.py中首先定义一个协议状态机类。该类保存了节点和边。节点为协议状态,边为触发该状态的事件。
  • 并且还定义了绘制图像、保存状态机,加载状态机的属性。
    • from graphviz import Digraph  # 导入graphviz的Digraph用于绘图
      import pickle  # 导入pickle模块用于序列化和反序列化对象
      
      
      # 定义节点的数据结构
      class Node:
          def __init__(self, code):
              # 初始化节点,设置节点的code
              self.code = code
      
          def __repr__(self):
              # 返回节点的字符串表示
              return f"Node(code={self.code})"
      
      
      # 定义边的数据结构
      class Edge:
          def __init__(self, source, target, event):
              # 初始化边,设置源节点、目标节点和触发事件
              self.source = source
              self.target = target
              self.event = event
      
          def __repr__(self):
              # 返回边的字符串表示
              return f"Edge(source={self.source}, target={self.target}, event={self.event})"
      
      
      # 创建有限状态机
      class FSM:
          def __init__(self):
              # 初始化自定义状态机,创建一个状态机对象并初始化节点和边的存储
              self.fsm = Digraph()  # 使用graphviz的有向图
              self.nodes = {}  # 用于存储节点的字典
              self.edges = []  # 用于存储边的列表
      
          def add_node(self, node):
              # 添加节点到图中
              self.nodes[node.code] = node  # 将节点存储在字典中
              self.fsm.node(node.code)  # 在有向图中添加节点
      
          def add_edge(self, edge):
              # 添加边到图中
              self.edges.append(edge)  # 将边存储在列表中
              self.fsm.edge(edge.source, edge.target, label=edge.event)  # 在有向图中添加边
      
          def __repr__(self):
              # 返回图的字符串表示
              return f"FSM(nodes={self.nodes}, edges={self.edges})"
      
          def draw_graph(self, filename="fsm_graph"):
              # 绘制图
              self.fsm.render(filename, format='png', cleanup=True)  # 渲染图并保存为文件
      
          def save_to_file(self, filename):
              # 保存图到文件
              with open(filename, 'wb') as file:
                  pickle.dump(self, file)  # 使用pickle序列化并保存对象
      
          @staticmethod
          def load_from_file(filename):
              # 从文件加载图
              with open(filename, 'rb') as file:
                  return pickle.load(file)  # 使用pickle反序列化并返回对象
  • 在initialize.py中初始化协议状态机。
    • from fsm import FSM, Edge, Node
      
      if __name__ == "__main__":
          fsm = FSM()  # 创建自定义有向图对象
      
          # 添加节点
          fsm.add_node(Node("220"))  # 添加节点
          fsm.add_node(Node("200"))
          fsm.add_node(Node("331"))
          fsm.add_node(Node("230"))
          fsm.add_node(Node("150"))
          fsm.add_node(Node("226"))
          fsm.add_node(Node("221"))
      
          # 添加边
          fsm.add_edge(Edge("220", "200", "OPTS UTF8 ON"))  # 添加边从节点1到节点2,事件为:OPTS UTF8 ON
          fsm.add_edge(Edge("200", "331", "USER webadmin"))
          fsm.add_edge(Edge("331", "230", "PASS 222"))
          fsm.add_edge(Edge("230", "200", "PORT 192,168,182,1,195,206"))
          fsm.add_edge(Edge("200", "150", "LIST"))
          fsm.add_edge(Edge("150", "226", ""))
          fsm.add_edge(Edge("226", "221", "QUIT"))
      
          # 打印图的表示
          print(fsm)
      
          # 绘制图并保存
          fsm.draw_graph(filename="fsm")
      
          # 保存图到pkl文件
          fsm.save_to_file("fsm.pkl")
    • 运行生成两个文件,fsm.pkl为协议状态机对象文件,fsm.png为协议状态机图。
  • 在load.py中加载保存的协议状态机对象,并更新状态机。
    • from fsm import FSM, Edge, Node
      
      if __name__ == "__main__":
          fsm = FSM.load_from_file("fsm.pkl")
          
          # 添加边
          fsm.add_edge(Edge("200", "221", "QUIT"))
      
          # 打印图的表示
          print(fsm)
      
          # 保存图到pkl文件
          fsm.save_to_file("fsm1.pkl")
      
          # 绘制图并保存
          fsm.draw_graph(filename="fsm1")
    • 运行后,状态机中加入了一条新的边。
  • 24
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

恣睢s

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值