普贤教程 › 生态包
二维码实战
registry/qrcode 是纯 PuXian 实现的二维码:编码、解码、SVG、PBM、终端 ASCII 全都有,四级纠错、版本 1–10、自动选版本与最优掩码。它有个硬条件:必须编译跑,解释轨一张要 58 秒。
安装
bash
pxpkg add qrcode@0.2.0 && pxpkg install
px
import qrcode十行生成一个二维码
px
import qrcode def main(): var r = qrcode_encode("https://px.dzty.club", "M") if r.is_err(): print("失败:" + str(r.err())) return var version = r.ok()[0] var mask = r.ok()[1] var matrix = r.ok()[2] print("版本=" + str(version) + " 掩码=" + str(mask) + " 边长=" + str(qrcode_matrix_size(matrix))) print("深色模块=" + str(qrcode_count_black(matrix))) var svg = qrcode_svg(matrix, 4, 4) # scale=4px/模块,静区 4 模块 write_file("qr.svg", svg)
实测输出:
text
版本=2 掩码=7 边长=25 深色模块=328
接口
| 函数 | 说明 |
|---|---|
qrcode_encode(s, ec) | 自动选版本 + 最优掩码 → Ok([version, mask, matrix]) |
qrcode_encode_at(s, ec, v, mask) | 固定版本/掩码(-1 表示自动),用于对拍 |
qrcode_decode(matrix) | 解码,纠错能力内会自动修正错码 → Ok(str) |
qrcode_svg(matrix, scale, margin) | 矢量图字符串,可直接内联进 HTML |
qrcode_ascii(matrix) | 终端渲染,██/空格,含 4 模块静区 |
qrcode_pbm(matrix, quiet) | PBM 位图(P1,纯文本) |
qrcode_version(matrix) | 由矩阵边长反推版本 |
qrcode_matrix_size(matrix) / qrcode_module_at / qrcode_count_black | 尺寸、取模块、统计深色模块 |
纠错级 ec 取 "L" / "M" / "Q" / "H":L 约容 7% 污损,H 约 30%。同样内容用 H 会让版本变大(模块更多、图更密)。
往返验证:编出来还能解回去
px
var m = qrcode_encode("https://px.dzty.club", "M").ok()[2] print(qrcode_decode(m).ok()) # https://px.dzty.club var cn = qrcode_encode("中文内容测试:普贤二维码 0.2.0", "H").ok() print(cn[0]) # 5 ← 中文按 UTF-8 字节走 byte 模式,版本涨到 5 print(qrcode_decode(cn[2]).ok()) # 中文内容测试:普贤二维码 0.2.0
三种输出形态怎么选
| 形态 | 体积(上面那个链接) | 适用 |
|---|---|---|
qrcode_svg | 18,687 字节 | 网页、打印、任意缩放不虚 |
qrcode_pbm | 纯文本位图 | 要位图但不想引 PNG 编码器 |
qrcode_ascii | 34 行 × 每行 50 字符 | 终端里手扫、日志里留证据 |
本站的这种用法最省事:直接把 SVG 塞进 data:image/svg+xml;base64,…,前端 <img src> 就能显示,不用落文件。
性能:必须编译跑
| 阶段 | 解释轨 px run | 编译轨 px build |
|---|---|---|
| 编码一个 v2 二维码 | 57,850 ms | 33 ms |
| 解码 | —(等不起) | 2 ms |
| 生成 SVG | — | 19 ms |
这不是「慢一点」,是差 1700 倍同在解释轨跑一套完整流程,30 秒工具上限直接被超时杀掉。二维码属于「矩阵级计算 + 大量字符串拼装」,解释轨的每次变量访问都要查符号表,量级一大就崩。任何在请求里生成二维码的接口,必须走
px build 或 Ma 的 mode:"fast"。在 Web 接口里签发(Ma px_routes)
px
import qrcode def main(): var text = env("QUERY_STRING") # 实际项目请自己解析 query var r = qrcode_encode("https://px.dzty.club" + text, "M") if r.is_err(): print("Status: 400 Bad Request") print("Content-Type: text/plain; charset=utf-8") print("") print(str(r.err())) return var svg = qrcode_svg(r.ok()[2], 6, 4) print("Status: 200 OK") print("Content-Type: image/svg+xml; charset=utf-8") print("Cache-Control: public, max-age=3600") print("") print(svg)
先编译再上线用 Ma 的
--px-probe qr.px 只编译不执行,确认产物能跑(0.22.0 起有这条命令)。别让 57 秒的解释轨进生产。坑
1. 解释轨超时是「杀进程组」,请求直接 504/500
Ma 的 timeout_ms 到点会杀掉脚本进程组。二维码这种重计算脚本,解释轨永远跑不完。
2. 中文会推高版本
一个汉字 3 字节(UTF-8),走 byte 模式。14 个汉字 = 42 字节,配 H 级已经到版本 5。内容越长,模块越密,打印/手机扫的成功率越低——长链接先短化,再生成。
3. 静区(margin)不能省
扫描器靠静区定位。SVG 的 margin 默认 4 模块,别为了「好看」裁成 0;贴在深色底上时,还要给码加白底,否则扫不出。
4. qrcode_decode 不是 OCR
它解的是矩阵([[bool…]]),不是图片。拍张照片喂进去不行——要先生成矩阵或从图里自己采样出矩阵。纠错能修「错码字」,修不了「拍歪了」。
和 barcode 包的分工
二维码是二维码,装得下 URL 和中文;registry/barcode 是一维码(EAN-13 / EAN-8 / Code128 等),只装数字或短串,适合商品条码。两者都纯函数、都建议编译跑。