【问题标题】:How to parse a DOT file in Python如何在 Python 中解析 DOT 文件
【发布时间】:2015-02-04 05:08:18
【问题描述】:

我有一个以 DOT 文件形式保存的传感器。我可以使用 gvedit 看到图形的图形表示,但是如果我想将 DOT 文件转换为可执行的转换器,我可以测试转换器并查看它接受哪些字符串以及不接受哪些字符串。

在我在 Openfst、Graphviz 及其 Python 扩展中看到的大多数工具中,DOT 文件仅用于创建图形表示,但如果我想解析文件以获得可以测试的交互式程序怎么办换能器的琴弦?

是否有任何库可以完成这项任务,还是我应该从头开始编写它?

正如我所说,DOT 文件与我设计的模拟英语形态的传感器有关。这是一个巨大的文件,但为了让您了解它的样子,我提供了一个示例。假设我想创建一个转换器来模拟英语在名词和复数方面的行为。我的词典只有三个词(书、男孩、女孩)。在这种情况下,我的传感器看起来像这样:

直接从这个DOT文件构造:

digraph A {
rankdir = LR;
node [shape=circle,style=filled] 0
node [shape=circle,style=filled] 1
node [shape=circle,style=filled] 2
node [shape=circle,style=filled] 3
node [shape=circle,style=filled] 4
node [shape=circle,style=filled] 5
node [shape=circle,style=filled] 6
node [shape=circle,style=filled] 7
node [shape=circle,style=filled] 8
node [shape=circle,style=filled] 9
node [shape=doublecircle,style=filled] 10
0 -> 4 [label="g "];
0 -> 1 [label="b "];
1 -> 2 [label="o "];
2 -> 7 [label="y "];
2 -> 3 [label="o "];
3 -> 7 [label="k "];
4 -> 5 [label="i "];
5 -> 6 [label="r "];
6 -> 7 [label="l "];
7 -> 9 [label="<+N:s> "];
7 -> 8 [label="<+N:0> "];
8 -> 10 [label="<+Sg:0> "];
9 -> 10 [label="<+Pl:0> "];
}

现在根据单词测试这个转换器意味着如果你用book+Pl 喂它它应该吐回books,反之亦然。我想看看如何将点文件转换为允许进行此类分析和测试的格式。

【问题讨论】:

  • 我们有机会看到 .dot 文件吗?
  • 一个 DOT 文件表示一个由节点和边组成的图。我猜节点是输入或输出点,两个节点之间的边代表运输。如果您显示 .dot 文件,您可能会获得更多有用的评论和/或答案。
  • 我刚刚更新并添加了一个示例。

标签: python parsing dot morphological-analysis transducer


【解决方案1】:

您可以从使用 https://code.google.com/p/pydot/ 加载文件开始。从那里开始编写代码以根据输入字符串遍历内存中的图应该相对简单。

【讨论】:

  • 您能详细说明一下吗?我知道 pydot,我知道你可以在那里加载一个点文件。 pydot 中的dot_parser 将点文件转换为一些内部类表示。但我不确定如何使用它。 Pydot 基本上是 Graphviz afaik 的一个接口。
  • @schmutter:见这里:stackoverflow.com/a/22935664/4323 - 你可以加载边缘。如果你想要一个更全功能的图形库,请参阅code.google.com/p/python-graph,它还可以加载 Dot 文件,并且包含算法。
  • 我无法使用(当前版本)pydot;它说它需要pyparsing。我下载了 pyparsing 的最新版本,但是 pydot 试图从 pyparsing 中导入一些不存在的东西。 Grr >:(
【解决方案2】:

安装graphviz 库。然后尝试以下操作:

import graphviz
graphviz.Source.from_file('graph4.dot')

【讨论】:

  • 这并不是真正解析 DOT 文件。
  • 你是对的,它没有像 OP 要求的那样将文件解析成有用的结构。但是,渲染图(在 Spyder 中)就足够了,这解决了我的问题!
  • 如果我这样做,从技术上讲,我正在使用 Python 解析文件,现在我可以将其转储为其他格式。所以答案是有效的,OP 没有要求避免使用第三方库。
【解决方案3】:

另一个路径,以及在dot 文件中查找循环的简单方法:

import pygraphviz as pgv
import networkx as nx

gv = pgv.AGraph('my.dot', strict=False, directed=True)
G = nx.DiGraph(gv)

cycles = nx.simple_cycles(G)
for cycle in cycles:
    print(cycle)

【讨论】:

  • 看起来不错,但目前无法安装。 pip install pygraphvizpip3 install pygraphviz 一样失败。
  • @JohnnyFromBF - 在什么平台上?我可以在 Mac 和 Linux 上运行它,但在 Windows 配置上遇到问题(使用 Anaconda)。
  • 我正在使用最新的 Debian Buster。
  • @JohnnyFromBF - 从内存中,您需要同时安装 Graphviz 和 libgraphviz-dev 之类的东西,以获得构建先决条件。如果这不起作用,请发布您看到的错误。
【解决方案4】:

使用它在 python 中加载一个 .dot 文件:

graph = pydot.graph_from_dot_file(apath)

# SHOW as an image
import tempfile, Image
fout = tempfile.NamedTemporaryFile(suffix=".png")
graph.write(fout.name,format="png")
Image.open(fout.name).show()

【讨论】:

    【解决方案5】:

    Guillaume 的回答足以在 Spyder (3.3.2) 中渲染图形,这可能会解决一些人的问题。

    如果你真的需要像 OP 那样操作图表,那将会有点复杂。部分问题在于 Graphviz 是一个图 rendering 库,而您正在尝试 分析 图。您尝试做的类似于从 PDF 文件逆向工程 Word 或 LateX 文档。

    如果您可以假设 OP 示例的良好结构,那么正则表达式就可以工作。我喜欢的一句格言是,如果你用正则表达式解决了一个问题,那么现在你有两个问题。尽管如此,对于这些情况,这可能是最实际的做法。

    以下是要捕获的表达式:

    • 您的节点信息:r"node.*?=(\w+).*?\s(\d+)"。捕获组是种类和节点标签。
    • 您的边缘信息:r"(\d+).*?(\d+).*?\"(.+?)\s"。捕获组是源、接收器和边缘标签。

    要轻松试用它们,请参阅 https://regex101.com/r/3UKKwV/1/https://regex101.com/r/Hgctkp/2/

    【讨论】:

    • 嗯,不,这与尝试对 PDF 文件进行逆向工程并不完全一样。至少不会写入 Word 或 Latex 文件。在这里,我们要从文件中构造一个内部计算机表示,一个解析树。这个操作是由 graphviz 程序在生成其输出之前执行的。
    【解决方案6】:

    我还没有尝试过上面的示例,但是NetworkX 有一个read_dot 函数,通过将文件转换为具有良好分析和分析能力的图形对象,这可能是解决此问题的好方法测试图表。

    【讨论】:

      猜你喜欢
      • 2015-04-26
      • 1970-01-01
      • 1970-01-01
      • 2010-12-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-10
      • 1970-01-01
      相关资源
      最近更新 更多