ISEE小语
通过Python画流程图,在日常工作中特定的场景中会使用到,本次在实践中遇到的问题一步一步的解决,有心分享,有使用到的同学可共勉!
在Python中,使用graphviz库可以非常方便地绘制流程图。graphviz是一个开源的图形可视化软件,可以生成各种图形,包括流程图。
先看实际效果
注:流程图有些细节可能与实际不符,请忽略^^
接下来,我们一步一步的操作,以下可能会有些啰嗦,别介意,因为第一次使用,踩坑了!
前期准备
环境
Pycharm
Python 3.9.16
三方库
pip install graphviz==0.20.3
安装软件
安装Graphviz软件,是必须的,在各个系统的安装如下:
macOS:使用Homebrew安装
brew install graphviz
Linux:使用包管理器安装(以Ubuntu为例)
sudo apt-get install graphviz
Windows:下载安装程序
https://graphviz.org/download/
小栈使用的是Windows系统,这里着重介绍一下安装步骤:
1、下载,小栈直接下载第一个
默认下载最新的即可,如果遇到不兼容的情况,可以下载其他较低的版本,在官网中都可以找到,根据实际情况而定!
2、右击graphviz-install-12.1.2-win64.exe,以管理员身份运行
3、根据提示安装
注:在这里选择加入环境变量,就不需要手动设置了
4、重启系统方可使用
小栈亲测,在windows 10下面安装完成后,需要重启一下系统才可以使用,其他系统,暂不清楚!
基本使用
简单流程图
# -*- coding: utf-8 -*-
from graphviz import Digraph
def create_flowchart():
dot = Digraph(comment='Simple Flowchart')
# 添加节点
dot.node('A', '开始')
dot.node('B', '步骤 1')
dot.node('C', '步骤 2')
dot.node('D', '结束')
# 添加边(有向)
dot.edges(['AB', 'BC', 'CD'])
# 保存并显示
dot.render('simple_flowchart', format='png', view=True)
create_flowchart()
看一下结果:
中文变成了乱码,试了一下英文的情况没有这问题,那接下来针对中文乱码的问题解决一下。
这个时候,我们需要设置字体属性,以SimSun为例:
# -*- coding: utf-8 -*-
from graphviz import Digraph
def create_flowchart():
dot = Digraph(comment='Simple Flowchart')
# 设置全局字体属性(以SimSun为例)
fontname = 'SimSun'
dot.attr(fontname=fontname)
# 添加节点
dot.node('A', '开始', fontname=fontname)
dot.node('B', '步骤 1', fontname=fontname)
dot.node('C', '步骤 2', fontname=fontname)
dot.node('D', '结束', fontname=fontname)
# 添加边(有向)
dot.edges(['AB', 'BC', 'CD'])
# 保存并显示
dot.render('simple_flowchart_02', format='png', view=True)
create_flowchart()
再看一下结果:
复杂流程图
复杂流程图,我们添加了不同节点形状、判断和字体大小
使用Graphviz中的shape属性来设置节点的形状:
开始节点(通常用椭圆形):shape='ellipse'
判断节点(通常用菱形):shape='diamond'
过程节点(通常用长方形):shape='box'
# -*- coding: utf-8 -*-
from graphviz import Digraph
def create_flowchart():
dot = Digraph(comment='Complexity Flowchart')
# 设置全局字体属性(以SimSun为例)
fontname = 'SimSun'
fontsize = '10'
dot.attr(fontname=fontname, splines='ortho')
# 添加节点并设置形状
dot.node('开始', '开始', shape='ellipse', fontname='SimSun')
dot.node('步骤1', '步骤 1', shape='box', fontname='SimSun')
dot.node('步骤2', '步骤 2', shape='box', fontname='SimSun')
dot.node('条件判断', '是否通过', shape='diamond', fontname='SimSun')
dot.node('结束', '结束', shape='ellipse', fontname='SimSun')
# 添加边
dot.edge('开始', '步骤1')
dot.edge('步骤1', '步骤2')
dot.edge('步骤2', '条件判断')
dot.edge('条件判断', '步骤1', xlabel='不通过', fontname='SimSun', constraint='false', fontsize=fontsize)
dot.edge('条件判断', '结束', xlabel='通过', fontname='SimSun', fontsize=fontsize)
# 保存并显示
dot.render('complexity_flowchart', format='png', view=True)
create_flowchart()
看一下结果:
附:
ellipse - 默认椭圆形
box - 矩形
diamond - 菱形
circle - 圆形
plaintext - 仅文本,不显示边框
hexagon - 六边形
octagon - 八边形
triangle - 三角形
parallelogram - 平行四边形
trapezium - 梯形
多样化流程图
多样化流程图,我们添加了不同节点的颜色,及横向和纵向流程的配合使用。换个说法就是美化。
使用Graphviz中的rankdir属性来设置流程图的方向:
设置LR:从左到右(横向)
设置RL:从右到左(横向)
设置TB:从上到下(纵向)
设置BT:从下到上(纵向)
# -*- coding: utf-8 -*-
from graphviz import Digraph
def create_flowchart():
dot = Digraph(comment='Complexity Flowchart')
# 设置全局字体属性(以SimSun为例)
fontname = 'SimSun'
fontsize = '10'
dot.attr(fontname=fontname, splines='ortho', rankdir='TB')
# 添加节点并设置形状
dot.node('开始', '开始', shape='ellipse', fontname='SimSun', style='filled', color='lightblue')
dot.node('步骤1', '步骤 1', shape='box', fontname='SimSun', style='filled', color='lightgreen')
dot.node('步骤2', '步骤 2', shape='box', fontname='SimSun', style='filled', color='lightgreen')
dot.node('步骤3', '步骤 3', shape='box', fontname='SimSun', style='filled', color='lightgreen')
dot.node('条件判断', '是否通过', shape='diamond', fontname='SimSun', style='filled', color='lightyellow')
dot.node('结束', '结束', shape='ellipse', fontname='SimSun', style='filled', color='lightcoral')
# 添加边
dot.edge('开始', '步骤1')
dot.edge('步骤1', '步骤2')
with dot.subgraph() as s:
s.attr(rank='same')
s.edge('步骤2', '步骤3', label='输出', fontname='SimSun', fontsize=fontsize)
dot.edge('步骤2', '条件判断')
dot.edge('条件判断', '步骤1', xlabel='不通过', fontname='SimSun', constraint='false', color='red', fontsize=fontsize)
dot.edge('条件判断', '结束', xlabel='通过', fontname='SimSun', fontsize=fontsize)
# 保存并显示
dot.render('complexity_flowchart_02', format='png', view=True)
create_flowchart()
结果:
实战
项目流程图
项目流程模块比较多,分为项目立项、需求阶段、设计阶段、研发阶段、测试阶段和项目结束。
这些阶段只是一个简化的,仅限学习,如果用到实际工作中,可能会有些许不适用,毕竟每个公司的流程多多少少会有些差异!
核心代码如下:
# -*- coding: utf-8 -*-
from graphviz import Digraph
def create_flowchart():
dot = Digraph(comment='项目简化流程图')
# 设置全局字体属性(以SimSun为例)
fontname = 'SimSun'
fontsize = '10'
dot.attr(fontname=fontname, splines='ortho', rankdir='TB')
# 需求阶段流程
with dot.subgraph(name='cluster_需求阶段') as c:
c.attr(label='需求阶段', fontname=fontname, color='blue')
c.node('需求分析', '需求分析', shape='box', fontname=fontname, style='filled', color='lightgreen')
c.node('PRD', '需求文档&原型', shape='box', fontname=fontname, style='filled', color='lightgreen')
c.node('PRD_1', '需求文档&原型文档', shape='plaintext', fontname=fontname, color='lightgreen')
c.node('需求评审', '需求评审', shape='diamond', fontname=fontname, style='filled', color='lightyellow')
# 添加边
c.edge('需求分析', 'PRD')
with c.subgraph() as c1:
c1.attr(rank='same')
c1.edge('PRD', 'PRD_1', label=' ', fontname=fontname, fontsize=fontsize)
c.edge('PRD', '需求评审')
dot.edge('需求评审', '需求分析', xlabel='不通过', fontname=fontname, constraint='false', color='red',
fontsize=fontsize)
# 设计阶段流程
with dot.subgraph(name='cluster_设计阶段') as s:
s.attr(label='设计阶段', fontname=fontname, color='blue')
s.node('UI设计', 'UI设计', shape='box', fontname=fontname, style='filled', color='lightgreen')
s.node('详细UI设计', '详细UI设计', shape='box', fontname=fontname, style='filled', color='lightgreen')
s.node('UI原型图', 'UI原型图', shape='plaintext', fontname=fontname, color='lightgreen')
s.node('设计评审', '设计评审', shape='diamond', fontname=fontname, style='filled', color='lightyellow')
# 添加边
s.edge('UI设计', '详细UI设计')
s.edge('详细UI设计', '设计评审')
with s.subgraph() as s1:
s1.attr(rank='same')
s1.edge('详细UI设计', 'UI原型图', label=' ', fontname=fontname, fontsize=fontsize)
s.edge('设计评审', 'UI设计', xlabel='不通过', fontname=fontname, constraint='false', color='red',
fontsize=fontsize)
# 研发阶段流程
with dot.subgraph(name='cluster_研发阶段') as y:
y.attr(label='研发阶段', fontname=fontname, color='blue')
y.node('技术分析', '技术分析', shape='box', fontname=fontname, style='filled', color='lightgreen')
y.node('技术设计', '技术设计', shape='box', fontname=fontname, style='filled', color='lightgreen')
y.node('技术设计文档', '技术设计文档', shape='plaintext', fontname=fontname, color='lightgreen')
y.node('技术评审', '技术评审', shape='diamond', fontname=fontname, style='filled', color='lightyellow')
y.node('编码', '编码', shape='box', fontname=fontname, style='filled', color='lightgreen')
y.node('研发完成', '研发完成', shape='box', fontname=fontname, style='filled', color='lightgreen')
# 添加边
y.edge('技术分析', '技术设计')
y.edge('技术设计', '技术评审')
with y.subgraph() as y1:
y1.attr(rank='same')
y1.edge('技术设计', '技术设计文档', label=' ', fontname=fontname, fontsize=fontsize)
y.edge('技术评审', '技术分析', xlabel='不通过', fontname=fontname, constraint='false', color='red',
fontsize=fontsize)
y.edge('编码', '研发完成')
# 测试阶段流程
with dot.subgraph(name='cluster_测试阶段') as t:
t.attr(label='测试阶段', fontname=fontname, color='blue')
t.node('测试分析', '测试分析', shape='box', fontname=fontname, style='filled', color='lightgreen')
t.node('测试用例', '测试用例', shape='box', fontname=fontname, style='filled', color='lightgreen')
t.node('测试用例文档', '测试用例文档', shape='plaintext', fontname=fontname, color='lightgreen')
t.node('用例评审', '用例评审', shape='diamond', fontname=fontname, style='filled', color='lightyellow')
t.node('执行测试', '执行测试', shape='box', fontname=fontname, style='filled', color='lightgreen')
t.node('测试报告', '测试报告', shape='box', fontname=fontname, style='filled', color='lightgreen')
# 添加边
t.edge('测试分析', '测试用例')
t.edge('测试用例', '用例评审')
with t.subgraph() as t1:
t1.attr(rank='same')
t1.edge('测试用例', '测试用例文档', label=' ', fontname=fontname, fontsize=fontsize)
t.edge('用例评审', '测试分析', xlabel='不通过', fontname=fontname, constraint='false', color='red',
fontsize=fontsize)
t.edge('研发完成', '执行测试')
t.edge('执行测试', '测试报告')
dot.node('开始', '项目开始', shape='ellipse', fontname=fontname, style='filled', color='lightblue')
dot.node('立项', '项目立项', shape='box', fontname=fontname, style='filled', color='lightgreen')
dot.edge('开始', '立项')
dot.edge('立项', '需求分析')
dot.edge('需求评审', 'UI设计', xlabel='通过', fontname=fontname, fontsize=fontsize)
dot.edge('需求评审', '技术分析', xlabel='通过', fontname=fontname, fontsize=fontsize)
dot.edge('需求评审', '测试分析', xlabel='通过', fontname=fontname, fontsize=fontsize)
dot.edge('技术评审', '编码', xlabel='通过', fontname=fontname, fontsize=fontsize)
dot.edge('设计评审', '编码', xlabel='通过', fontname=fontname, fontsize=fontsize)
dot.edge('用例评审', '执行测试', xlabel='通过', fontname=fontname, fontsize=fontsize)
dot.node('验收', '验收', shape='box', fontname=fontname, style='filled', color='lightgreen')
dot.node('部署实施', '部署实施', shape='box', fontname=fontname, style='filled', color='lightgreen')
dot.node('结束', '结束', shape='ellipse', fontname=fontname, style='filled', color='lightcoral')
dot.edge('测试报告', '验收')
dot.edge('验收', '部署实施')
dot.edge('部署实施', '结束')
# 保存并显示
dot.render('项目简化流程图', format='png', view=True)
create_flowchart()
结果:
终于完成了,是不是很Nice
总结
后台回复flowchart即可获取源码!
寄语:世间三美,明月,清风,眼前……
看到这儿的朋友帮点个“赞”和“在看”,谢谢支持~!
文章就分享到这儿,喜欢就点个赞吧!