python graphviz中文乱码_Graphviz的使用及中文乱码问题解决

诸多属性中,最常用的大概是label 了。

label可以决定节点、线段或子图片上要显示些什么。如果您的节点名很长的话,可以在程序内部取个简短的名称,之后透过短名称操作它,另外透过label 指定它的显示内容。

color、fillcolor、fontcolor 这些属性都是控制颜色用的,不过fillcolor 只有在style 被指定为"filled" 时才会生效。

线段属性方面。有向图中的箭头可透过arrowhead 与arrowtail 属性来指定头尾样式。至于线段本身,则可透过style 属性,指定不同类型的虚线与短截线。使用者还可以用dir 属性让箭头方向反过来。

另外还有一个image 属性,可以指定让node 显示图片,需要时也可参考看看。

4.3.3. rank

dot 语言中有一个叫作rank 的概念。

所谓的rank,在dot 语言中,含意比较接近于「等级」。他主要用在dot渲染器中。

请看以下的图:

图8:rank 示例。

很明显可以看出来,图片被从上到下分为四层-这就是rank。

下方是与上图对应的dot 陈述:

//demo7

digraph demo{

a -> b -> c -> d;

b -> { e f };

}

观察程序,可看出rank是如何被指定的。

其基本规则在于:每个线段的头端,都会比尾端多出一个等级(在图上面就是往下面一层)。

但等等,如果等级指定的语句彼此矛盾呢?

修改以上程式码为:

//demo8

digraph demo{

a -> b -> c -> d [label = "rank增加"];

b -> { e f } [label = "rank增加"];

f -> a [label = "不影响rank"];

}

图9:rank 示例。

看上面的结果,显然rank 的指定是「先说先赢」的。

除了基本规则外,rank也可以透过属性来加以调节,有必要时要参看手册。

5. 在脚本中使用Graphviz

5.1. 在shell中使用Graphviz

在了解了 Graphviz DOT 语言的基础知识之后,您可以开始创建脚本,从而动态创建一个 DOT 文件。这允许您动态创建始终准确且保持最新的图表。

示例1是一个 bash shell 脚本,它连接到 Hardware Management Console (HMC),收集托管服务器和逻辑分区 (LPAR) 的相关信息,然后使用这些信息来创建 DOT 输出。

示例1 hmc_to_dot.sh

#!/bin/bash

HMC="$1"

serverlist=`ssh -q -o "BatchMode yes" $HMC lssyscfg -r sys -F "name" | sort`

echo "graph hmc_graph{"

for server in $serverlist; do

echo " \"$HMC\" -- \"$server\" "

lparlist=`ssh -q -o "BatchMode yes" $HMC lssyscfg -m $server -r lpar -F "name" | sort`

for lpar in $lparlist; do

echo "    \"$server\" -- \"$lpar\" "

done

done

echo "}"

通过提供一个 HMC 服务器名称作为参数传递给脚本,便可运行此脚本。该脚本将传递的第一个参数设置为 $HMC 变量。设置 $serverlist 变量的方法是连接到 HMC 并获得该 HMC 控制的所有托管服务器的清单。在这些托管服务器上进行循环,而脚本将为每台托管服务器打印一行 "HMC" -- "server" ,这表明 Graphviz 在每台 HMC 与其托管服务器之间绘制了一条直线。此外针对每台托管服务器,脚本再次连接到 HMC 并获得该托管系统上的 LPAR 清单,然后通过它们循环打印一行 "server" -- "LPAR"。这表明 Graphviz 在每台托管服务器与其 LPAR 之间都绘制了一条直线。

此脚本要求您在运行脚本的服务器与 HMC 之间设置 Secure Shell (SSH) 密钥身份验证。

事例1`脚本的输出:

graph hmc_graph{

"hmc01" -- "test520"

"test520" -- "lpar2"

"test520" -- "lpar3"

"hmc01" -- "test570"

"test570" -- "aixtest01"

"test570" -- "aixtest02"

"test570" -- "aixtest03"

"hmc01" -- "test510"

"test510" -- "lpar1"

}

从脚本生成图的具体方法是运行以下命令:./hmc_to_dot.shhmc_server_name|dot-Tpng-ohmc_graph.png

上述命令运行脚本,并动态创建 DOT 语言的文本,然后将这些输出传递给 dot 命令,以便让它创建一个文件名为 hmc_graph.png 的图表。图 10 显示了创建的图表。

图 10 从 hmc_to_dot.sh 脚本创建的图表

备注:这里的脚本的使用和具体的环境有关,详细参考[3],具体的语境为AIX小型机上的Virtual I/O Servers 有关,很明显,我不能可能有的AIX小型机来测试,所以这个图不是我自己生成的,但是,这里在shell脚本中生成dot的源码确实值得学习。

5.2. 在Python中使用Graphviz

dot不是一个真正的编程语言,但它是很容易与真正的编程交互。可以绑定多种编程语言,包括Java,Perl和Python。更轻量级替代是从喜欢的语言中生成dot代码。 这样做将使您自动化整个图形生成过程。

Python写的用来生成dot的例子。此示例脚本展示了如何以最小的努力绘制的Python类层次。

# dot.py

"Require Python 2.3 (or 2.2. with from __future__ import generators)"

def dotcode(cls):

setup='node [color=Green,fontcolor=Blue,fontname=Courier]\n'

name='hierarchy_of_%s' % cls.__name__

code='\n'.join(codegenerator(cls))

return "digraph %s{\n\n%s\n%s\n}" % (name, setup, code)

def codegenerator(cls):

"Returns a line of dot code at each iteration."

# works for new style classes; see my Cookbook

# recipe for a more general solution

for c in cls.__mro__:

bases=c.__bases__

if bases: # generate edges parent -> child

yield ''.join([' %s -> %s\n' % ( b.__name__,c.__name__)

for b in bases])

if len(bases) > 1: # put all parents on the same level

yield " {rank=same; %s}\n" % ''.join(

['%s ' % b.__name__ for b in bases])

if __name__=="__main__":

# returns the dot code generating a simple diamond hierarchy

class A(object): pass

class B(A): pass

class C(A): pass

class D(B,C): pass

print dotcode(D)

函数dotcode需要一个类,并返回绘制类的系谱树所需的dot源代码。codegenerator生成的代码,遍历类的祖先的列表(类的方法解析序列中),并确定边和节点的层次结构。Codegenerator是一个在每次迭代中返回一行的dot代码的生成器。返回一个迭代产生点阵码在每次迭代。生成器是最近添加到Python中的工具,在处理生成文本或源代码的目的问题时特别方便。脚本的输出是如下不言自明的dot代码:

digraph hierarchy_of_D {

node [color=Green,fontcolor=Blue,font=Courier]

B -> D

C -> D

{rank=same; B C }

A -> B

A -> C

object -> A

}

处理命令:python dot.py | dot -Tpng -o x.png

生成的图片如下:

备注:例子来自参考4。

6. 中文乱码问题

如果graphviz中出现了中文乱码问题,可以采用两种方法来处理,一种就是上面的将文本保存为UTF8(Ubuntu下默认为UTF8,Windows下默认为ASNI),并将中文包含在英文的引号(“”)中。另一种方法多一个将图或结点的字体属性设置为中文字体的步骤,具体步骤如下:

l 保存为UTF8格式

l 设置中文字体,常见的中文字体的对应的名字如下:

黑体:SimHei 宋体:SimSun 新宋体:NSimSun 仿宋:FangSong 楷体:KaiTi

仿宋_GB2312:FangSong_GB2312 楷体_GB2312:KaiTi_GB2312

下列以编译原理的处理流程图为例演示,第二种中文处理方法,此外,其中还演示了使用一些复杂的属性。

compile_process.dot程序代码:

//compile_process.dot

digraph G {

edge [fontname="FangSong"];

node [shape=box, fontname="FangSong" size="20,20"];

{

Lexical_Analyzer [label="词法分析器"];

Syntax_Analyzer [label="语法分析器"];

Semantic_Analyzer [label="语义分析"];

Intermediate_Code_Generator [label="中间代码生成器" ];

Machine_Independent_Code_Optimizer [label="机器无关代码优化器" ];

Code_Generator [label="代码生成器" ];

Machine_Dependent_Code_Optimizer [label="机器相关代码优化器"];

}

node[shape=plaintext, fontname="KaiTi" ]{

character_stream [label="字符流"];

target_machine_code [label="目标机器语言" ];

}

character_stream ->Lexical_Analyzer;

Lexical_Analyzer ->Syntax_Analyzer [label="符号流"];

Syntax_Analyzer  ->Semantic_Analyzer  [label="语法树"];

Semantic_Analyzer  ->Intermediate_Code_Generator  [label="语法树"] ;

Intermediate_Code_Generator->Machine_Independent_Code_Optimizer  [label="中间表示形式"];

Machine_Independent_Code_Optimizer  ->Code_Generator  [label="中间表示形式"];

Code_Generator ->Machine_Dependent_Code_Optimizer [label="目标机器语言"];

Machine_Dependent_Code_Optimizer->target_machine_code ;

}

dot渲染生成的图,其他的格式(fdp等)渲染的效果不太好:

fdp渲染的该图(效果非常不好):

小结

Graphviz的确实一个非常的强大的工具,而且其官方的文档还非常全面。更多的内容,参考其官方的文档,地址为:http://www.graphviz.org/Documentation.php。

[2]Graphviz中文乱码问题

[4]An Introduction to GraphViz and dot :http://www.linuxdevcenter.com/pub/a/linux/2004/05/06/graphviz_dot.html

你可能感兴趣的:(python,graphviz中文乱码)