PyGWalker 贡献者开发指南:从环境搭建到一键热重载与 CI 验证的完整工作流
2026/9/14 9:21:50 网站建设 项目流程

PyGWalker 贡献者开发指南:从环境搭建到一键热重载与 CI 验证的完整工作流

【免费下载链接】pygwalkerPyGWalker: Turn your dataframe into an interactive UI for visual analysis项目地址: https://gitcode.com/GitHub_Trending/py/pygwalker

PyGWalker 是一个把 pandas/polars/pyarrow 等 DataFrame 转换为可交互可视化 UI 的 Python 库,其仓库由 Python 包(pygwalker/)与 React 前端(app/)两个半区组成并打包进同一个 wheel。本文基于仓库根目录的 CONTRIBUTING.md 与其详细版本 docs/CONTRIBUTING.md,完整梳理本地开发环境搭建、前后端双栈构建、python scripts/dev.py一键热重载开发栈、以及提交前验证与 CI 对齐的全部命令与参数;读完本文,你将掌握一套可直接复现的 PyGWalker 本地贡献流程,并理解其底层构建与加载机制。

贡献指南的入口设计:一份短入口,一份权威详述

仓库将贡献者工作流拆成两层文档,避免重复维护:

  • 根目录 CONTRIBUTING.md 是面向新贡献者(包括编码 Agent)的入口,它把读者引向 AGENTS.md——后者提供仓库地图、Python 与前端两半区的构建方式,以及"一条命令"的开发栈python scripts/dev.py(带前端实时重载与集中日志)。
  • 详细的贡献者工作流统一维护在 docs/CONTRIBUTING.md,覆盖:
    • Python 可编辑安装与测试命令;
    • 前端依赖安装、构建、类型检查与 Playwright smoke 测试;
    • 通过appdev:preinstall脚本可选地构建本地 Graphic Walker 源码;
    • 热重载开发工作流(docs/DEVELOPMENT.md)与项目架构(docs/ARCHITECTURE.md);
    • CI 与包构建的预期行为。

这种"短入口 + 单一权威详述"的设计让开发笔记与故障排查页可以统一链接到一份维护中的真源文档。

环境准备:版本对齐是第一步

在开始前,请确保本机满足以下版本要求(与 CI 保持一致):

依赖版本要求说明
Python3.10 或更新仓库pyproject.tomlrequires-python = ">=3.10"与之对应
Node.js22.x必须与 CI 使用的版本一致(见下文 CI 说明)
Yarn1.x经典版 Yarn

从源码看,scripts/dev.py 在执行时会用_resolve_exe依次查找可执行文件:优先使用当前 Python 解释器同目录下的同名可执行文件(即 venv 内的yarn/jupyter),再回退到PATH搜索;找不到时直接退出并给出安装提示。这提醒我们:确保 Node.js 22.x 与 Yarn 1.x 在当前 shell 的PATH,是后续所有命令能跑通的前提。

Python 环境搭建:可编辑安装 + dev 依赖

从仓库根目录执行:

python -m venv venv source venv/bin/activate pip install -e ".[dev]"

Windows 下激活环境使用:

venv\Scripts\activate

要点说明:

  • pip install -e ".[dev]"采用可编辑安装(editable install),代码改动即时生效,无需重复安装;
  • [dev]pyproject.toml中定义的开发依赖组,包含测试、lint、notebook 运行等工具(如pytestruffnbmake);
  • pyproject.toml的 Hatch 配置中,editable 构建同样会走hatch-jupyter-builder钩子并执行前端dev命令(build_cmd = "dev"),因此 venv 创建完成后建议紧接着完成下一步的前端依赖安装,保证pygwalker/templates/dist/中有可用 bundle。

前端环境搭建:依赖、构建与产物

进入app/目录安装前端依赖:

cd app yarn install

构建全部前端 bundle:

yarn build

如果只想快速重建主应用 bundle(适合只改app/src时的本地迭代):

yarn build:app

关于这两个命令的差异,app/package.json 中的脚本定义给出了精确答案:

"build": "yarn typecheck && vite build && vite build --mode=dsl_to_workflow && vite build --mode=vega_to_dsl", "build:app": "vite build"

yarn build会先跑 TypeScript 类型检查(tsc --noEmit),再依次产出四个产物;而yarn build:app只执行一次vite build不做类型检查,也不构建 DSL 转换辅助 bundle,因此只适合本地快速迭代,不能用于 CI 或最终提交流程(详见"验证"一节)。

构建产物会写入pygwalker/templates/dist/。这些是生成产物,已被 git 忽略,除非发布流程明确要求,否则不应提交(详见 AGENTS.md 与 docs/ARCHITECTURE.md 中的说明)。四个 bundle 与用途如下:

Bundle构建入口加载方
pygwalker-app.es.jsapp/src/index.tsxanywidget 传输(默认pyg.walk路径)
pygwalker-app.iife.jsapp/src/index.tsxiframe 传输 / 静态to_html()
dsl-to-workflow.umd.jsapp/src/lib/dslToWorkflow.ts内核侧 DSL→workflow 转换
vega-to-dsl.umd.jsapp/src/lib/vegaToDsl.ts内核侧 Vega→DSL 转换

使用本地 Graphic Walker 源码进行联调

npm 包@kanaries/graphic-walker默认从app/yarn.lock安装。如果你需要针对本地 Graphic Walker checkout 测试 PyGWalker,需把它放在 PyGWalker 仓库根目录下,使其成为app/的兄弟目录:

pygwalker/ +-- app/ +-- graphic-walker/ +-- packages/ +-- graphic-walker/

然后在启动 PyGWalker 前端之前先构建 Graphic Walker:

cd app yarn dev:preinstall

dev:preinstall实际执行的内容(见 app/package.json):

cd ../graphic-walker/packages/graphic-walker yarn --frozen-lockfile yarn build

如果../graphic-walker/packages/graphic-walker目录不存在,则跳过此命令,回退到 lockfile 锁定的 npm 依赖即可。

开发服务器 / 热重载:一条命令的完整开发栈

针对前端迭代,项目提供了一键开发栈:每次改动都会重建应用并借助 anywidget HMR 把新代码热重载进已打开的 notebook widget 中:

python scripts/dev.py

这条命令会同时启动两个长驻进程,并把两者的输出同时"分流(tee)"到终端与logs/目录下的独立文件(详见 scripts/dev.py 的实现):

  • frontendcd app && yarn dev:build,即vite build --watch,每次你编辑app/src就会重建pygwalker/templates/dist/pygwalker-app.es.js,输出到logs/frontend.log
  • jupyter:以PYGWALKER_DEV=1ANYWIDGET_HMR=1环境变量启动jupyter lab(内核会继承这些变量),输出到logs/jupyter.log

scripts/dev.py还会通过PYGWALKER_LOG_FILE把内核侧的 PyGWalker Python 日志集中到logs/pygwalker.log(通过env.setdefault设置,不覆盖用户显式选择)。启动时脚本会先等待前端首次构建完成(在日志中匹配 Vite 的built in完成标记,见_wait_for_first_build),再拉起 JupyterLab,避免内核找不到 bundle。

两个进程都启动后,在 notebook 单元里无需任何特殊设置,直接正常使用 PyGWalker:

import pandas as pd, pygwalker as pyg pyg.walk(pd.DataFrame({"x": [1, 2, 3], "y": [4, 5, 6]}))

随后编辑app/src下的任意文件,等logs/frontend.log中出现built in …表示重建完成,widget 就会就地热重载——通常无需重跑单元;改动较大时重跑单元即可。按Ctrl+C可干净地停掉整套服务。

热重载为什么能工作

其原理记录在 docs/DEVELOPMENT.md 与 docs/ARCHITECTURE.md 中,关键在pygwalker/services/anywidget_widget.py

  • 正常安装WalkerAnyWidget._esmpygwalker-app.es.js内容字符串(导入时内嵌),与历史行为完全一致;
  • 开发模式(设置PYGWALKER_DEV=1ANYWIDGET_HMR=1):_esm指向该 bundle 的文件路径,anywidget 从磁盘读取,并在 HMR 下通过watchfiles监听该文件,每当vite build --watch重写它就把新代码推送到前端。

由于该切换完全由环境变量显式开启,在未设置这些标志的普通安装中,加载行为逐字节不变——对最终用户没有任何影响。

dev.py 常用参数

参数作用
--no-jupyter只跑前端 watch 构建
--no-frontend只启动 JupyterLab(bundle 已构建好时)
--jupyter-port N指定 JupyterLab 端口
--no-browser不自动打开浏览器(输出不是 TTY 时自动启用,如 Agent 运行场景)
--log-dir DIR更改日志目录(默认logs/

另外还有一个历史遗留的 Vite dev-server +GlobalVarManager.set_component_url("/pyg_dev_app/")+jupyter-server-proxy方案,它只驱动已废弃的低层 iframe 兼容渲染器;旧的env='Jupyter'别名现在会统一选择 anywidget,显式调用兼容方法的完整说明见 docs/DEVELOPMENT.md。新开发工作一律优先走 anywidget HMR 路径。

日志:一处查看所有输出

scripts/dev.py把所有输出集中到仓库根目录的logs/(git 忽略):

文件内容
logs/frontend.logVite 构建/watch 输出——留意built in …(重建完成)与 TypeScript 错误
logs/jupyter.logJupyterLab 服务器输出——打开 notebook 的 URL 与 token 在这里
logs/pygwalker.log内核侧 PyGWalker Python 日志(经PYGWALKER_LOG_FILE设置)

Python 侧日志还支持两个与编排器无关的环境变量(由pygwalker/utils/log.py处理):PYGWALKER_LOG_FILE=/path/to/file.log追加写入文件,PYGWALKER_LOG_LEVEL=DEBUG调整详细程度(默认INFO)。前端运行时的日志(如 comm 错误)出现在浏览器 devtools 控制台,不会写入logs/;面向用户的错误会以应用内 toast 通知呈现。

验证与提交前检查:本地复刻完整 CI

提交前,可以用一条命令在本地跑完整的 CI 流程(前端构建 + Playwright smoke 测试 + notebook 测试 + Python lint/测试):

python scripts/local_ci.py # 可加 --skip-frontend / --skip-notebooks 缩小范围

scripts/local_ci.py 是 GitHub Actions Auto CI 工作流的本地等价实现,支持--skip-frontend--skip-notebooks--legacy-modin-deps(镜像 Ubuntu Python 3.11 modin CI 分支)三个开关。也可以按下面的分步命令逐个执行。

Python 侧:格式化、lint 与测试

在仓库根目录(venv 已激活)执行:

python -m ruff check pygwalker tests scripts bin pygwalker_tools python -m ruff format --check pygwalker tests scripts bin pygwalker_tools python -X faulthandler -W error::DeprecationWarning:pygwalker -m pytest -o faulthandler_timeout=60 tests python -m pytest --nbmake --nbmake-kernel=python tests/*.ipynb

逐条说明:

  • 前两条用ruff分别做 lint 检查与格式检查(pyproject.toml中配置了target-version = "py310"line-length = 120);
  • 第三条运行单元测试,同时开启 faulthandler、把pygwalker包内的DeprecationWarning提升为错误,并设置faulthandler_timeout(文档中为 60 秒;scripts/local_ci.py 中的 CI 等价实现使用 300 秒);
  • 第四条用nbmake逐本执行tests/*.ipynb中的 notebook,验证 notebook 场景可运行。

需要留意:pygwalker_tools/是一个活跃打包的辅助命名空间,当前支持面为pygwalker_tools.metrics,由tests/test_metrics_tools.py覆盖,因此它必须保持在 lint、测试、wheel 与 sdist 的路径中——这也解释了上述命令为什么显式包含pygwalker_tools

前端侧:类型检查、构建与 smoke 测试

app/目录下执行:

yarn typecheck yarn build yarn playwright install chromium yarn test:front_end
  • yarn typecheck对应tsc --noEmit --pretty false
  • yarn build是全量构建(typecheck + 四个 bundle);
  • yarn playwright install chromium首次运行需要安装 Chromium;app/playwright.config.ts 配置了testDir: "./tests"、30 秒用例超时、基于http://127.0.0.1:8769的 webServer(yarn dev --host 127.0.0.1),CI 下会复用/重建该服务器;
  • yarn test:front_end运行 Playwright smoke 测试(app/tests/gwalker-smoke.spec.ts)。

再次强调:yarn build:app虽然便于快速迭代主 bundle,但不运行 TypeScript 检查、也不构建 CI 与包构建所必需的 DSL 转换辅助 bundle,提交前必须走完整的yarn build或至少yarn typecheck

包构建

在仓库根目录执行:

python -m build --wheel --no-isolation

当前包构建会在构建 wheel 时重新构建前端 bundle,而不是复用已有的pygwalker/templates/dist文件。这一行为由 pyproject.toml 中的 Hatch 配置保证:

[tool.hatch.build.hooks.jupyter-builder] dependencies = ["hatch-jupyter-builder"] build-function = "hatch_jupyter_builder.npm_builder" ensured-targets = ["pygwalker/templates/dist/pygwalker-app.iife.js"] optional-editable-build = true [tool.hatch.build.hooks.jupyter-builder.build-kwargs] path = "app" build_dir = "./build" build_cmd = "build"

ensured-targets确保构建产物存在;wheel 构建钩子会在app/下执行build(即 typecheck + 四个 bundle),因此发布出的 wheel 始终包含刚构建的 bundle。这也解释了为什么pygwalker/templates/dist/被 git 忽略、按需重建、永不手工提交。前端构建也可直接由 scripts/compile.sh 完成(自动处理 yarn 缺失时的全局安装,再执行yarn && yarn build)。

CI 说明:工作流与仓库配置对齐

GitHub workflows 的现状(详见 docs/CONTRIBUTING.md 的 CI Notes):

  • 用 Node.js 22.x 构建前端资产;
  • 运行前端 Playwright smoke 测试;
  • 再运行 Python 测试矩阵;
  • Python 包构建也会安装 Node.js 与 Yarn,因为 Hatch 构建钩子在 wheel 创建期间会重建前端。

因此,任何 CI 工作流的改动都要与app/package.jsonpyproject.tomlscripts/compile.sh保持一致,否则本地验证与远端 CI 会出现偏差。

提交前后的小结与常见问题

一次典型的贡献流程可以概括为:

  1. 搭建环境:Python 3.10+ venv +pip install -e ".[dev]"cd app && yarn install,首次yarn build生成pygwalker/templates/dist/
  2. 迭代开发python scripts/dev.py一键启动 watch 构建与 JupyterLab,编辑app/src即可看到热重载;涉及消息协议(pygwalker/communications/protocol.py)改动时,运行python scripts/generate_comm_protocol_ts.py重新生成app/src/interfaces/comm.generated.ts并重建前端,切不可手改生成文件;
  3. 本地验证python scripts/local_ci.py(或分步执行 Python 的 ruff/pytest/nbmake 与前端 typecheck/build/playwright);
  4. 打包检查python -m build --wheel --no-isolation,确认 Hatch 钩子重建了前端 bundle。

常见问题(完整清单见 docs/DEVELOPMENT.md 的 Troubleshooting 一节):

  • "Missing PyGWalker frontend asset" 错误:bundle 尚未构建,先cd app && yarn build,或等scripts/dev.py完成首次构建;
  • 前端改动不生效:确认logs/frontend.log出现built in …,且 JupyterLab 以ANYWIDGET_HMR=1启动(编排器会自动设置);改动较大时重跑单元或重启内核;
  • React 版本错误等异常:在app/下执行干净重建(rm -rf node_modules && yarn install && yarn build,如需手动清理依赖);
  • 千万别提交pygwalker/templates/dist/:它是生成产物,wheel 构建(与 CI)会通过 Hatch 钩子按需重建。

遵循上述工作流,无论是人类贡献者还是编码 Agent,都能以与 CI 完全一致的标准完成 PyGWalker 的前后端开发与交付。

【免费下载链接】pygwalkerPyGWalker: Turn your dataframe into an interactive UI for visual analysis项目地址: https://gitcode.com/GitHub_Trending/py/pygwalker

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询