普贤教程 › 基础教程
模块与导入
PuXian 的模块系统只有一件事:把别的文件里的函数变成当前文件可用的函数。没有命名空间前缀,没有 package 声明。
三种 import
px
import "lib.px" # 同目录的源文件 import std.strings # 标准库模块 import mysql # 生态包(registry,需先 pxpkg install)
| 写法 | 来源 | 说明 |
|---|---|---|
import "x.px" | 项目内文件 | 相对当前文件的路径,引号不能省 |
import std.xxx | stdlib/ | 27 个标准库模块 |
import 包名 | registry/ 或 .px_modules/ | 裸名字,需要项目里装过 |
项目内拆分文件
把公共函数放进一个文件,其他文件 import 它:
px
# lib/mathutil.px def clamp(x, lo, hi): if x < lo: return lo if x > hi: return hi return x def pct(a, b): if b == 0: return 0.0 return a / b * 100
px
# app.px import "lib/mathutil.px" print(str(clamp(120, 0, 100))) print(str(pct(3, 4)))
text
100 75.0
import 之后,被导入文件的函数直接进入当前作用域——不需要 mathutil.clamp() 这样的前缀。代价是命名要自己管好,别在两个文件里定义同名函数。
标准库
px
import std.strings print(str(index_of("中文ab", "b"))) print(str(last_index_of("a.b.c", ".")))
text
3 3
标准库模块清单见 标准库概览。lib 内部互相 import 时用的是文件相对路径;你只需要 import 顶层那个模块。
生态包(registry)
registry 里有 195 个包。项目里装依赖的标准流程:
sh
pxpkg init --name myapp # 生成 px.toml pxpkg add mysql@0.2.0 # 写进依赖 pxpkg install # 落地到 .px_modules/ pxpkg list # 看装了哪些
px
import mysql解析顺序裸名 import 会先找项目里的
.px_modules/,再找 PX_REGISTRY 指向的 registry 目录。没有 pxpkg install 就直接 import,会得到「找不到模块」。import 的路径规则
import "x.px"是相对当前文件的路径;子目录写成import "lib/x.px"。import std.xxx会依次尝试./stdlib、../stdlib、PX_STDLIB。- 在解压目录之外跑
px,标准库要靠PX_STDLIB环境变量指过去。
不要跨目录 import
正确做法是把公共库复制一份进本目录,用同目录相对路径引用。
import "../other/lib.px" 在本地能跑,但把它部署到 Ma 的 px_routes 时会失败:Ma 编译时只把「脚本所在目录」打包成沙箱,跨目录的目标不在里面,编译只能跳过该 import,运行期报「未定义变量」。正确做法是把公共库复制一份进本目录,用同目录相对路径引用。
循环依赖
两个文件互相 import 时行为不保证。把公共部分抽到第三个文件,两边都 import 它——这也顺便让依赖方向变成单向。
模块里的顶层代码
被 import 的文件如果有顶层 print,第一次 import 时会执行一次。所以库文件里只放函数与常量声明,不要放有副作用的语句:
px
# ❌ 库文件里不要这样 print("lib 被加载了") # ✅ 只声明 def helper(): return 1
组织建议
| 规模 | 建议结构 |
|---|---|
| 单文件脚本 | 一个 .px,不拆 |
| 小工具(3–5 个文件) | 同目录:main.px + lib.px + 各自模块 |
| 服务(10+ 文件) | 按职责分目录,每个目录内自包含,公共库复制或显式同步 |
公共库要能独立测试把纯函数(无 IO、无网络)集中在
lib.px,配一个 t_lib.px 断言脚本;这样改公共库时能一分钟内回归。