news 2026/10/14 16:16:07

SpiffWorkflow:纯 Python 工作流引擎的架构、BPMN/DMN 能力与实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SpiffWorkflow:纯 Python 工作流引擎的架构、BPMN/DMN 能力与实战指南
  • 后端
  • 工作流自动化
  • 流程编排
  • 低代码

【免费下载链接】SpiffWorkflow

A powerful workflow engine implemented in pure Python

项目地址:https://gitcode.com/gh_mirrors/sp/SpiffWorkflow
点击查看免费下载

SpiffWorkflow 是一个用纯 Python 实现的工作流引擎,提供通用的核心执行库,并附带解析与执行 BPMN / DMN 图的扩展模块。阅读本文,你将了解它的设计动机与核心对象模型(Specification 与 Instance、任务状态机),掌握pip安装方式、依赖与运行环境,并能通过make与uv运行完整测试;同时结合源码印证 BPMN 解析、Python 脚本引擎与 DMN 决策表等关键能力的实现。

项目定位与设计动机

从 README 的定义看,SpiffWorkflow 是一个「用纯 Python 实现的工作流引擎(workflow engine implemented in pure Python)」。它建立在 Workflow Patterns 倡议(initiative)的基础工作之上,并在 2020 与 2021 年期间为 BPMN / DMN 处理扩展了大量支持。当前仓库的版本号可在 SpiffWorkflow/version.py 中查到。

README 的Motivation一节阐明了创建该库的目标:为 Python 生态中的低代码(low-code)业务应用提供支撑。其核心思路是:

  • 让非开发者能够用 BPMN 图(可视化 diagram)来描述复杂的业务流程;
  • 配合一个强大的 Python 脚本引擎,让脚本能够无缝地嵌入到这些图中运行;
  • SpiffWorkflow 负责解析这些图并执行它们。

作者认为,虽然 Java 生态已存在多种类似工具,但 Python 语言的广泛采用与易用性,使其在构建低代码应用上具有天然优势。这一动机直接决定了仓库的整体结构——一个通用核心库,加上围绕 BPMN / DMN 的解析与执行扩展模块。

核心特性总览:BPMN、DMN 与纯 Python 工作流

README 的Features一节列出了三大能力。以下结合仓库源码逐项印证。

BPMN:解析与执行复杂的流程元素

从 BpmnParser 的PARSER_CLASSES映射可以看到,解析器为大量 BPMN 元素建立了「解析器类 → 任务规格类」的映射,覆盖了 README 提到的 pools / lanes、多实例任务、子工作流、定时事件、信号、消息、边界事件与循环等复杂组件,例如:

PARSER_CLASSES = { full_tag('startEvent'): (StartEventParser, StartEvent), full_tag('endEvent'): (EndEventParser, EndEvent), full_tag('userTask'): (TaskParser, UserTask), full_tag('subProcess'): (SubWorkflowParser, SubWorkflowTask), full_tag('exclusiveGateway'): (ConditionalGatewayParser, ExclusiveGateway), full_tag('parallelGateway'): (GatewayParser, ParallelGateway), full_tag('inclusiveGateway'): (ConditionalGatewayParser, InclusiveGateway), full_tag('callActivity'): (CallActivityParser, CallActivity), full_tag('transaction'): (SubWorkflowParser, TransactionSubprocess), full_tag('adHocSubProcess'): (AdHocSubprocessParser, AdHocSubprocess), full_tag('scriptTask'): (ScriptTaskParser, ScriptTask), full_tag('serviceTask'): (TaskParser, ServiceTask), full_tag('boundaryEvent'): (BoundaryEventParser, BoundaryEvent), # ... 以及 receiveTask / sendTask / eventBasedGateway 等 }

BpmnParser还维护着消息、信号、错误、升级(escalation)、关联(correlation)与数据存储(data store)等全局索引,并在add_bpmn_xml中按固定顺序(先数据仓库、再图索引、后流程与协作)完成解析,以保证跨节点引用的正确解析。docs/bpmn/supported.rst 进一步给出了支持元素清单,并特别标注了两个抽象实现:Service Task 与 Data Store只被解析、不提供内置执行/读写机制,这是阅读文档时需要注意的能力边界。

DMN:与 Python 执行引擎深度集成的决策表

DMN(Decision Model and Notation)能力集中在SpiffWorkflow/dmn包。从 DMNEngine 的实现看,decide方法会遍历决策表的规则行(rules),逐条用__check_rule判断输入是否命中;result方法则根据hit_policy组织输出——例如在COLLECT命中策略下,每个输出会聚合成值数组再合并,而UNIQUE策略在命中第一条规则后即返回。这印证了 README 所述「DMN 基线实现与 Python Execution Engine 深度集成」。

Python 工作流:以代码或内部 JSON 数据结构驱动

README 强调「保留了直接在代码中构建工作流,或基于内部 JSON 数据结构运行工作流的能力」。这一能力由SpiffWorkflow/specs模块承载。specs 模块入口 导出了大量任务规格(WorkflowSpec、Simple、Join、Merge、MultiChoice、MultiInstance、SubWorkflow、Transform等),对应 Workflow Patterns 中的各类控制流模式。

以 docs/core/tutorial/nuclear.py 为例,可以在纯 Python 中定义一个「核弹发射需将军与总统双重确认」的工作流:

from SpiffWorkflow.specs.WorkflowSpec import WorkflowSpec from SpiffWorkflow.specs.ExclusiveChoice import ExclusiveChoice from SpiffWorkflow.specs.Simple import Simple from SpiffWorkflow.specs.Cancel import Cancel from SpiffWorkflow.operators import Equal, Attrib class NuclearStrikeWorkflowSpec(WorkflowSpec): def __init__(self): WorkflowSpec.__init__(self) general_choice = ExclusiveChoice(self, 'general') self.start.connect(general_choice) cancel = Cancel(self, 'workflow_aborted') general_choice.connect(cancel) president_choice = ExclusiveChoice(self, 'president') cond = Equal(Attrib('confirmation'), 'yes') general_choice.connect_if(cond, president_choice) # ...

该工作流也可以用等价的 JSON 表示,通过 docs/core/tutorial/serialize.py 与 docs/core/tutorial/deserialize.py 借助JSONSerializer完成序列化 / 反序列化,对应的示例数据见 docs/core/tutorial/nuclear.json。运行工作流时,docs/core/tutorial/start.py 展示了Workflow(spec)与workflow.run_all(halt_on_manual=False)的基本用法。

轻量依赖与运行环境

README 的Dependencies一节明确:项目「极力最小化外部依赖」,仅依赖lxml来解析 XML 文档。这与 pyproject.toml 的声明一致:

dependencies = ["lxml"] requires-python = ">=3.10" license = { text = "lGPLv3" } [project.optional-dependencies] dev = ["build", "coverage", "unittest-parallel"] doc = ["sphinx", "sphinx_rtd_theme"]

由此可知其适用前提与限制:

  • 运行时只需lxml一个第三方库;
  • Python 版本要求>=3.10([project]中requires-python,且classifiers覆盖 3.10–3.14);
  • 开发依赖(dev额外项)包含build、coverage与unittest-parallel,用于构建、覆盖率统计与并行测试;
  • 项目采用setuptools构建,版本号动态取自SpiffWorkflow.version.__version__。

代码风格方面,README 声明遵循PEP8;pyproject.toml 中的[tool.ruff]进一步将line-length设为 140、target-version设为py310。

安装方式

README 的Installation一节给出安装命令:

pip install spiffworkflow

注意:包名在 PyPI 侧为spiffworkflow,而 pyproject.toml 中声明的name为SpiffWorkflow,import时使用的顶层包为SpiffWorkflow。

核心对象模型:Specification 与 Instance、任务状态机

README 将详细文档指向spiff.works,而仓库内的 docs/concepts.rst 则系统阐述了库的核心抽象,这也是理解一切实现的关键。

Specification(规格)与 Instance(实例)的二分是 SpiffWorkflow 的基础:

  • 规格对象(WorkflowSpec/TaskSpec)描述结构与行为——即「工作流每次执行时可能走的所有路径」;
  • 实例对象(Workflow/BpmnWorkflow与Task)描述一次运行的当前状态,即「实际走过的那条/那些路径」。

规格是唯一的(一个工作流对应一份模型,一个任务对应一份规格),而实例是不唯一的(同一规格可被执行多次,同一任务规格在一次执行中也可被多次到达)。从 Workflow 类 的实现看,实例在构造时基于spec建立task_tree(根任务初始为FUTURE态),并通过_predict预测后代任务状态。

任务状态机则被抽象为三大类、多个具体状态(见 TaskState):

类别状态含义
PREDICTEDMAYBE位于条件分支,可能运行
PREDICTEDLIKELY位于条件分支的默认输出路径
DEFINITEFUTURE一定会运行
DEFINITEWAITING需满足前置条件才能变为READY
DEFINITEREADY前置条件满足,可运行
DEFINITESTARTED已开始但未结束
FINISHEDCOMPLETED成功完成
FINISHEDERROR失败结束
FINISHEDCANCELLED运行前或运行中被取消

任务从PREDICTED或FUTURE起步,经过一个或多个DEFINITE状态,最终进入FINISHED状态。TaskState以位掩码(bitmask)表示各状态(如MAYBE=1、READY=16、COMPLETED=64),便于用掩码组合地筛选任务。SpiffWorkflow 任务状态转移图 直观展示了从MAYBE / LIKELY → FUTURE → READY → COMPLETE,以及WAITING、CANCELLED的转移关系。

此外,docs/concepts.rst 还描述了驱动任务执行的**钩子(hooks)**机制(_update_hook、_on_ready_hook、run_hook、_on_complete_hook、_on_error_hook、_on_trigger)以及任务预测(_predict_hook),并区分了数据在Workflow / Task / Task internal / Task spec四个层级上的存储位置——这些都是构建上层应用时绕不开的概念。

运行测试

README 的Tests一节给出了标准环境与uv环境两套完整的测试命令。

标准环境:

pip install -e .[dev] make tests make tests-par make tests-cov

使用uv:

uv sync --extra dev make RUN='uv run' tests make RUN='uv run' tests-par make RUN='uv run' tests-cov

结合 Makefile 可以看到每个 target 的具体行为,便于理解其含义:

  • tests:$(RUN) python -m unittest discover -vs tests/SpiffWorkflow -p *Test.py -t .,即按*Test.py模式在tests/SpiffWorkflow下递归发现并运行单元测试;
  • tests-par:依赖unittest-parallel,若未安装会提示用pip install -e .[dev]或uv sync --extra dev安装,命令为$(RUN) unittest-parallel -qbs tests/SpiffWorkflow -p *Test.py -t .;
  • tests-cov:cd tests/SpiffWorkflow && $(RUN) coverage run --source=SpiffWorkflow -m unittest discover -v . "*Test.py",在运行测试的同时采集覆盖率。

$(RUN)前缀正是make RUN='uv run'的注入点——它让同一套 target 在「直接 python」与「uv run」之间切换。仓库测试覆盖 BPMN 并行网关、事件、序列化版本迁移、DMN 决策表、Camunda 扩展等大量场景(tests/下共有上百个*Test.py文件),可作为验证上述能力的可靠依据。

包结构与核心模块

从仓库顶层结构看,SpiffWorkflow包分为「通用核心」与「BPMN / DMN / Camunda / Spiff 扩展」两大阵营,其核心类关系可参考 SpiffWorkflow 类图:

  • 通用核心:workflow.py(Workflow实例)、specs/(WorkflowSpec及各种任务规格)、serializer/(Serializer、JSONSerializer、XMLSerializer等);
  • BPMN 模块:bpmn/parser/(BpmnParser、ProcessParser、TaskParser、事件解析器)、bpmn/script_engine/(PythonScriptEngine)、bpmn/specs/(BPMN 任务规格与 mixin)、bpmn/serializer/(含版本迁移);
  • DMN 模块:dmn/engine/(DMNEngine)、dmn/parser/、dmn/specs/;
  • Camunda / Spiff 扩展:分别位于 camunda/ 与 spiff/,提供 Camunda 扩展解析、以及 Spiff 自定义扩展(服务任务、用户任务、数据对象、脚本前后置、重试等)。

其中,Python 脚本引擎是连接「图」与「代码」的关键:PythonScriptEngine 提供validate(用ast.parse校验表达式)、evaluate(在任务数据上下文中求值)与execute(执行脚本)方法,并在异常时通过create_task_exec_exception定位出错行号与内容,包装为WorkflowTaskException。其文档字符串明确指出:若对eval()/exec()不放心,可提供专门子类以其他方式解析并执行脚本——这是扩展脚本执行的安全入口。

支持、贡献与许可

  • 支持:README 的Support一节说明可从 Sartography 获取 SpiffWorkflow 的商业支持,并提供了社区沟通渠道。
  • 贡献:README 的Contribute一节欢迎 Pull Request,要求:检查代码格式、确保所有测试通过、附带可证明新代码按预期工作的额外测试,并在适用时于 PR 中引用 issue 编号。
  • 许可:项目以GNU Lesser General Public License (LGPL) v3发布。这一声明在 README 的 License 一节、docs/index.rst 的 License 一节,以及 pyproject.toml 的license = { text = "lGPLv3" }与classifiers中保持一致。
  • 致谢:README 的Credits and Thanks一节列出了对项目的关键贡献者与支持方(包括 Virginia 大学对构建通用 BPMN 工作流系统的支持),以及对 BPMN.js 等外部工具的感谢,体现了这是一个长期、社区驱动的开源项目。

小结

SpiffWorkflow 以「一个通用核心库 + BPMN / DMN 扩展模块」的组织方式,把 Workflow Patterns、BPMN 图与 Python 脚本引擎结合起来:核心库负责任务状态机、数据层级与序列化的通用执行,bpmn/dmn/camunda/spiff模块则分别承担解析、决策与扩展。其依赖极简(仅lxml)、安装即用(pip install spiffworkflow),并配有覆盖并行、事件、DMN、版本迁移等场景的完整测试。理解「Specification / Instance」二分与任务状态机(MAYBE / FUTURE / WAITING / READY / COMPLETED等)是进一步深入该引擎、构建上层应用的核心前提。

  • 后端
  • 工作流自动化
  • 流程编排
  • 低代码

【免费下载链接】SpiffWorkflow

A powerful workflow engine implemented in pure Python

项目地址:https://gitcode.com/gh_mirrors/sp/SpiffWorkflow
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/14 16:15:52

SO_REUSEPORT 实现多进程端口共用与连接分发

1. 为什么一个端口能被四个进程同时 bind?从“地址已在使用”报错说起刚接触网络编程的人,几乎都踩过这个坑:写了个简单的 TCP 服务器,bind()时突然报错Address already in use。查日志、关进程、netstat -tuln | grep :8080&…

作者头像 李华
网站建设 2026/10/14 16:15:06

Python网络版中国象棋实战:从socket通信到联机对弈

简介:基于Python的网络版中国象棋是一份包含服务器端与双客户端的完整项目源码,面向需要实战练习Python网络编程和桌面游戏开发的学习者,帮助解决在局域网环境下实现双人实时对战的问题。压缩包共31个文件,大小6.67MB,…

作者头像 李华
网站建设 2026/10/14 16:14:49

海洋数据机器学习实战:从传统方法到深度学习与物理约束

1. 海洋数据到底长什么样:先搞清楚你面对的是什么很多做机器学习的朋友一听到“海洋科学”四个字,第一反应是“不就是把陆地上的模型搬到海里去吗”。我一开始也这么想,直到真正接触了几个海洋观测项目的数据之后才发现,这个想法有…

作者头像 李华