Graphviz 是一款强大的开源软件包,主要用于绘制图 (graphs),包括有向图、无向图、流程图、状态机图等。它提供了命令行工具(如 dot
、neato
、circo
等)和一系列库接口,可以帮助开发者在 算法可视化、数据结构可视化、流程建模、网络拓扑展示 等场景中快速产出美观而专业的图表。
下面将从以下几个方面介绍 Graphviz 的使用与特点:
Graphviz 的安装
在 Linux / macOS 上安装
- Ubuntu / Debian 系:
sudo apt-get update sudo apt-get install graphviz
- macOS(使用 Homebrew):
brew install graphviz
在 Windows 上安装
- 访问 Graphviz 官方下载页面;
- 根据操作系统选择对应的安装包(.exe)并安装;
- 安装时可勾选“Add Graphviz to the system PATH for current user”或手动将其
bin
目录添加到系统 Path 中。
安装完成后,你可以在命令行输入:
dot -V
若能正常显示版本信息,则说明 Graphviz 安装成功。
Graphviz 的基本概念与语法
Graphviz 提供了一种类似描述语言的文件格式(.dot 或 .gv),通过简单的文本语法即可定义节点(nodes)、边(edges)以及样式(attributes)等。
一个最基本的 Graphviz DOT 文件示例:
digraph G {
A -> B;
B -> C;
A -> C [label="Edge A-C", color=red];
A [shape=box, style=filled, fillcolor=lightblue];
}
其中:
- digraph 表示这是一个有向图 (directed graph);若是无向图则用
graph
并使用--
表示边。 - A -> B 表示从节点 A 到节点 B 的一条有向边;无向图则写作
A -- B
。 - [label=“Edge A-C”, color=red]:给边设置标签以及颜色等样式。
- A [shape=box, style=filled, fillcolor=lightblue]:给节点 A 设置方框形状、背景色为浅蓝色等属性。
主要语法元素
- graph / digraph:声明是无向图还是有向图。
- 节点 (node):用独特的标识符 (ID) 表示,比如
A
、"some label"
, 也可用数字。 - 边 (edge):
A -- B
(无向)、A -> B
(有向)。 - 子图 (subgraph):用于分组节点或设置局部布局、属性,可以指定
{ ... }
范围内的内容共享某些设置。 - 属性 (attribute):可附加在图、边、节点上,例如
label
,shape
,color
,style
,rankdir
,rank=same
等。
将 DOT 文件渲染为图像
如果保存为 example.dot
,可使用命令行渲染成 PNG、SVG 等多种格式:
dot -Tpng example.dot -o example.png
dot -Tsvg example.dot -o example.svg
-T
指定目标格式,-o
指定输出文件路径,dot
会自动进行布局并生成图像。
常用布局引擎
Graphviz 提供了多个布局引擎,每种引擎都有各自的适用场景:
- dot:层次化/有向图布局,适用于展示流程图、层级结构。
- neato:基于力导向的布局,适用于无向图或非层次结构的数据可视化。
- fdp:与 neato 相似,也是一种力导向布局算法。
- sfdp:适合大规模的稀疏图。
- circo:圆环布局,多用于环状或循环结构的可视化。
- twopi:辐射布局,以树的根节点为中心向外扩散。
在命令行或代码中,可以通过执行引擎的名称来生成布局,如:
neato -Tpng graph.gv -o graph_neato.png
fdp -Tpng graph.gv -o graph_fdp.png
或在 .dot
文件中通过 graph [layout=neato];
指定所需引擎。
在 Python 中使用 Graphviz
如果你想在 Python 代码中动态生成和渲染 Graphviz 图,可以使用官方提供的 graphviz PyPI 包:
pip install graphviz
4.1 基本用法
from graphviz import Digraph
dot = Digraph(comment='My Graph')
# 添加节点
dot.node('A', 'Node A')
dot.node('B', 'Node B')
# 添加边
dot.edge('A', 'B', label="A->B Edge")
# 渲染并保存为 PDF(默认使用 dot 布局引擎)
dot.render('my_graph_output', view=True, format='pdf')
dot.node('A', 'Node A')
:第一个参数是内部 ID,第二个参数是显示的标签。dot.edge('A', 'B')
:表示从 A 到 B 的边。dot.render(...)
:渲染并保存文件;view=True
表示渲染后自动在系统的默认应用中打开结果图。
如果报错:FileNotFoundError: [Errno 2] No such file or directory: ‘xdg-open’, 可以设置 view=False 关闭预览。
graphviz
库调用了xdg-open
来尝试打开生成的 PDF 文件,但未找到该工具,导致FileNotFoundError
。xdg-open
是xdg-utils
包中的一个工具,用于在默认应用程序中打开文件或 URL。例如,打开 PDF 文件时,xdg-open
会自动选择系统默认的 PDF 阅读器。- 在大多数 Linux 发行版中,可以通过 sudo apt-get install xdg-utils 安装。因服务器无界面,安装后可能仍然不可预览。
4.2 设置属性
dot.node('A', 'Node A', shape='box', style='filled', color='lightblue')
dot.edge('A', 'B', label='Edge A-B', color='red')
dot.graph_attr['rankdir'] = 'LR' # 图从左到右布局
在 Jupyter Notebook 中展示 Graphviz 图
在 Jupyter Notebook 中,可以使用 graphviz
包提供的显示组件,无需额外导出文件。只要在单元格的最后放置一个 dot
对象,Notebook 即可内嵌显示图像。
from graphviz import Digraph
dot = Digraph()
dot.node('A', 'Node A')
dot.node('B', 'Node B')
dot.edge('A', 'B')
dot # 在 Jupyter 中显示
若你想导出为文件,也可以继续使用 dot.render('filename')
。
常见示例与技巧
6.1 画流程图 / 状态机
digraph process {
rankdir=LR;
node [shape=rect];
Start -> Step1 [label="Initialize"];
Step1 -> Step2 [label="Process"];
Step2 -> End [label="Finalize"];
Start [shape=ellipse, style=filled, fillcolor=lightgreen];
End [shape=doublecircle, color=red];
}
6.2 子图聚类 (subgraph cluster)
Graphviz 可以在 .dot
文件中使用 subgraph cluster_xxx { ... }
来给一组节点画边框、背景色等。
digraph {
subgraph cluster_0 {
style=filled;
color=lightgrey;
node [style=filled,color=white];
A -> B -> C;
label = "Cluster 0";
}
subgraph cluster_1 {
node [style=filled];
D -> E;
label = "Cluster 1";
color=blue
}
C -> D;
}
6.3 同 rank 的节点对齐
有时希望同一“层级”的节点保持水平对齐,可以使用 { rank=same; Node1; Node2; }
:
digraph G {
A -> B -> C;
{ rank=same; B; D; }
B -> D;
}
小结
- Graphviz 通过简单的语法或交互式 Python 方式,让我们能轻松定义和呈现多种形式的图结构。
- 不同的布局引擎(
dot
,neato
,fdp
,circo
,twopi
)适合不同的可视化需求。 - 在 Python 中使用
graphviz
包能够动态生成和渲染,并与 Jupyter Notebook 结合实现交互式可视化。 - Graphviz 是算法可视化、流程设计、结构展示等领域的常用“利器”,无论是工程师还是研究人员,都能从中受益。
如需更深入的使用指南或更多示例,可以查看: