最近一直在用 dot 来画图,如果你不知道 dot 这个东西,那么 graphviz 应该听说过吧,graphviz 是 dot 语言的一个实现。dot 是一个绘图语言,可以表达有向图和无向图,用 dot 语言描述的图可以 render 成 png、jpeg、pdf、svg 等等各种格式,非常方便。
比如下面这个 dot 文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
digraph G { subgraph cluster_0 { style=filled; color=lightgrey; node [style=filled,color=white]; a0 -> a1 -> a2 -> a3; label = "process #1"; } subgraph cluster_1 { node [style=filled]; b0 -> b1 -> b2 -> b3; label = "process #2"; color=blue } start -> a0; start -> b0; a1 -> b3; b2 -> a3; a3 -> a0; a3 -> end; b3 -> end; start [shape=Mdiamond]; end [shape=Msquare]; } |
可以渲染成下面这个文件:
Mac 的 graphviz 提供了命令行的工具可以渲染 dot 文件。可以通过 brew 来安装: brew install graphviz
。
但是每次编辑然后切换到命令行渲染,再用 Preview 打开浏览,非常繁琐,这种文件修修改改是比较频繁的,预览体验很不好,比较合适的方法是用 jupyter 这样的 notebook 来实时渲染。Graphviz 目前没有可以直接在 jupyter 里面跑的 kernel,不过 Python 的封装是支持在 jupyter 看到结果的。这个缺点是你要写 Python 语言,调用 Python 的函数和方法,show 函数等等。不能写原生的 dot 语言。
我在这上面包了一层,调用这个包可以直接在 jupyter 的 cell 里面写 dot 了,项目的地址如下:
https://github.com/laixintao/jupyter-dot-kernel
这个 kernel 其实挺好写的,去看了一下文档,基本复用一下 IPython 的 kernel 就可以了。但是发送二进制数据回前端的 Response 结构很妖娆,文档也看不怎么明白,网上的资料也比较少…… 算是一个小坑吧,在这上面花了不少时间。最后是一拍脑袋,去找了其他 kernel 的代码看了一下才弄清楚的。贴在下面让大家感受下……
1 2 3 4 5 6 |
stream_content = { "metadata": {"image/png": {"width": width, "height": height}}, "data": {"image/png": data}, } self.send_response(self.iopub_socket, "display_data", stream_content) |
然后我还在 jupyter 里面写了一个教程(WIP),目前写了基础的教程, 看完之后基本都知道怎么样了。后面打算继续完善一些一些更高级的用法。教程的地址如下:
https://github.com/laixintao/learn-dot
我参考的主要是一些手册和文档,其实目前找到的也不是很多。那个 dot 文档竟然没有一个目录,有必要整理一下。
- dot 文档:
- The DOT Language
- Command-line Usage
- Output Formats
- Graph Attributes 这个文档比较关键,列举了所有可以用的属性
- Node Shapes
- Colors
- Arrow Shapes
- graphviz manual:
man dot
- dot guide 官方 PDF
可以试试 VS Code 的 dot 插件,可以实现实时预览。