Blankly / 安装与依赖边界
装了不等于能用:Blankly 在 Python 3.11 上装完就 import 失败
README 的安装说明只有两行:pip install blankly,然后 blankly init。这两步在 2026 年都还执行得下去——但中间缺了一环:装完之后 import blankly 会直接抛出 numpy 的二进制不兼容错误,连 blankly --help 都进不去。这一页把完整报错、依赖链成因和实测可用的处置顺序摊开写,你可以照着一步步复现。
怎么完整复现?每一步的命令与退出码
下表是本机在 2026-09-21 实际执行的命令序列。退出码 0 表示命令成功,所以「安装成功」和「导入失败」这两件看似矛盾的事可以同时成立。
| 步骤 | 执行的命令 | 退出码 | 结果 |
|---|---|---|---|
| 1. 建虚拟环境 | python -m venv v | 0 | 成功 |
| 2. 升级 pip | v\Scripts\python -m pip install --upgrade pip --quiet | 0 | 成功 |
| 3. 按 README 安装 | v\Scripts\python -m pip install blankly | 0 | 成功,下载 blankly-1.18.25b0-py3-none-any.whl |
| 4. 查看解析结果 | v\Scripts\python -m pip freeze | 0 | 得到 numpy 2.4.6、pandas 3.0.6 等 47 个包 |
| 5. 导入包 | v\Scripts\python -c "import blankly" | 0 | 抛异常:ValueError: numpy.dtype size changed |
| 6. 调 CLI | v\Scripts\python -m blankly --help | 1 | 失败,同一个异常在导入阶段就中断 |
| 7. 钉住 numpy | v\Scripts\python -m pip install "numpy<2" | 0 | numpy 降到 1.26.4 |
| 8. 再次导入 | v\Scripts\python -c "import blankly" | 0 | 成功,四个子模块全部 OK |
| 9. 再次调 CLI | v\Scripts\python -m blankly --help | 0 | 成功,列出 init 与 key |
blankly --help 确认命令行可用。在这个版本上,它会和 import 一起失败——因为它们都会触发 blankly/__init__.py 里的指标模块导入。所以「CLI 报错」并不是 CLI 本身的问题。失败时的完整堆栈是什么?每一层在说什么
把堆栈逐层读一遍,你会发现它其实直接指出了嫌疑对象。下面是未做任何删减的原始输出。
Traceback (most recent call last):
File "<frozen runpy>", line 189, in _run_module_as_main
File "site-packages\blankly\__init__.py", line 43, in <module>
import blankly.indicators as indicators
File "site-packages\blankly\indicators\__init__.py", line 1, in <module>
from blankly.indicators.indicators import *
File "site-packages\blankly\indicators\indicators.py", line 20, in <module>
import tulipy as ti
File "site-packages\tulipy\__init__.py", line 26, in <module>
from . import lib
File "tulipy\lib\__init__.pyx", line 3, in init tulipy.lib
ValueError: numpy.dtype size changed, may indicate binary incompatibility.
Expected 96 from C header, got 88 from PyObject
| 堆栈层次 | 它在告诉你什么 | 可推出的结论 |
|---|---|---|
blankly/__init__.py line 43 | 包在初始化阶段就无条件导入 blankly.indicators | 指标模块一旦导入失败,整个包都不可用,没有绕过路径 |
indicators.py line 20 | 它 import tulipy as ti | 报错来自第三方 C 扩展,不是 Blankly 自己的 Python 代码 |
tulipy/__init__.py → tulipy\lib\__init__.pyx | 安装目录里叫 tulipy,但 PyPI 包名是 newnewtulipy | 搜索报错时两个名字都要试,否则搜不到答案 |
init tulipy.lib | 失败点在 Cython 扩展的初始化函数里 | 这是编译期 ABI 问题,改 Python 代码解决不了 |
Expected 96 ... got 88 | 扩展编译时用的 numpy 头文件与运行时的 numpy 不是同一代 ABI | 降 numpy 到扩展支持的代际即可 |
pip install --force-reinstall 解决。这个错误与文件损坏无关,重装只会重新解析出同一个 numpy 2.x,然后把同一段堆栈再打印一次。为什么必然会走到这一步:依赖链上三个时间点错位
这不是偶发故障,而是三个时间点相互错位后的必然结果。把三个时间点摆在一起,问题就清楚了。
| 环节 | 时间点 | 当时的状态 | 与今天的冲突 |
|---|---|---|---|
| Blankly 的依赖声明 | 2023-07(最后发行) | 写的是 numpy (>=1.21.4),没有上限 | pip 会优先选最新版 numpy,也就是 2.x |
newnewtulipy 轮子 | 2022-11(最后上传) | 提供 cp37 / cp38 / cp39 / cp310 / cp311 轮子,编译目标为 numpy 1.x | 与 numpy 2.x 的 C-ABI 不兼容,导入即崩 |
| numpy 2.0 发布 | 2024 年(numpy 主版本跃迁) | ABI 发生变化,使用旧 ABI 编译的扩展需要重编 | 上游扩展已停更,没有人重编 |
| Blankly 的 Python 声明 | 2023-07 | README 与 classifiers 只列到 Python 3.10 | 3.12+ 连 newnewtulipy 轮子都没有,需本地编译工具链 |
alpaca-trade-api | 2024-01(最后上传) | 已是上游弃用的旧客户端 | 它把 urllib3 钉在 <2,又会与其它包互相约束 |
该选哪条处置路线?按 Python 版本与环境干净度
本机实测走的是路线 1。路线 2 和 3 是针对不同约束的替代方案,本站没有全部实测,因此会明确标注哪些是实测、哪些是依据轮子覆盖范围的推断。
| 方案 | 具体做法 | 适用场景 | 本站验证状态 |
|---|---|---|---|
| 方案 1:钉 numpy 上限 | 先 pip install "numpy<2" 再装 blankly,或把 numpy<2 写进自己的 requirements.txt | Python 3.10 / 3.11,需要一个能跑的环境 | 已实测通过:numpy 1.26.4 + 1.18.25b0,四个子模块导入正常 |
| 方案 2:用旧 Python | 建一个 Python 3.10 环境再装 | 需要贴合官方声明的支持范围 | 依据 README/classifiers 的支持声明,本站未实测;但 3.10 与 3.11 都会解析到 numpy 2.x,所以仍需钉上限 |
| 方案 3:源码安装 | 克隆仓库后改 setup.py 的依赖声明再本地安装 | 需要长期维护这份依赖,想把约束固化到项目里 | 依据仓库 setup.py/setup.cfg 的存在,本站未实测 |
| 方案 4:Python 3.12+ | 不适用 | — | 不可行:newnewtulipy 无 cp312/cp313 轮子,只能本地编译 C 扩展 |
numpy<2 写进 requirements.txt 是成本最低、可传递性最好的做法。照着做哪五步?从空目录到可以 import
每一步都给出真实命令、它做什么,以及你应该看到什么。如果某一步的输出与预期不同,先停下来核对,不要往下走。
建一个独立虚拟环境
命令:
python -m venv v(Windows 激活用v\Scripts\activate,macOS/Linux 用source v/bin/activate)。独立环境的价值在于:这条依赖链需要钉死 numpy 版本,如果装进全局环境,会影响你机器上其它项目。预期输出:命令无输出即成功,目录下出现v/。先钉住 numpy 上限,再装 Blankly
命令:
pip install "numpy<2"然后pip install blankly。顺序可以互换,但先钉上限能避免中间态出现一个装好却用不了的版本。预期输出:先看到 numpy 解析到 1.26.x,再看到blankly-1.18.25b0-py3-none-any.whl被安装。验证导入而不是只验证安装
命令:
python -c "import blankly, blankly.indicators, blankly.metrics; print('import ok')"。这一步是整页的核心——pip install的退出码不能证明包可用。预期输出:import ok。验证 CLI
命令:
python -m blankly --help。预期输出:列出两个子命令init与key。如果你看到的是login/deploy,说明你用的不是这个发行版,请以实际输出为准。把约束固化下来
命令:
pip freeze > requirements.txt。这样下一次换机器时,直接pip install -r requirements.txt就能复现同一套版本组合,不必再排查一遍。
怎么按 Python 版本与操作系统核对组合?
「能不能装」这件事在不同 Python 版本上的答案并不一样,因为决定因素是依赖轮子的标签覆盖,而不是 Blankly 本身。
| Python 版本 | 官方是否声明支持 | 依赖轮子是否覆盖 | 本站判断 |
|---|---|---|---|
| 3.7 / 3.8 / 3.9 | 是 | 是(cp37–cp39 轮子齐全) | 理论可行;但需注意 numpy 2.x 已不支持这些旧 Python,pip 会自动选到 numpy 1.x |
| 3.10 | 是(README 列出的最高版本) | 是(有 cp310 win/mac/linux 轮子) | 最贴合官方声明的组合;仍需确认 numpy 解析结果 |
| 3.11 | 未声明 | 是(有 cp311 win/mac/linux 轮子) | 本站实测环境:钉 numpy<2 后可完整使用 |
| 3.12 / 3.13 | 未声明 | 否(无 cp312/cp313 轮子) | 需要本地 C 编译工具链;本站不建议作为起步环境 |
| Windows | 未单独声明 | 有 win_amd64 轮子 | 本机(Windows)实测与文档描述一致 |
| macOS(Intel / Apple Silicon) | 未单独声明 | 有 macosx_10_9_x86_64 与 macosx_11_0_arm64 轮子 | 依据轮子清单推断可行,本站未实测 |
| Linux(x86_64) | 未单独声明 | 有 manylinux2014_x86_64 轮子 | 依据轮子清单推断可行,本站未实测 |
安装与依赖相关的高频问题
回答基于 2026-09-21 本机实测;涉及依赖版本号的部分会随上游变动,请以你机器上的实际解析结果为准。
为什么 pip install 成功但 import 失败?这不算装失败吗?
在 pip 的语义里,「安装成功」只表示下载与落盘完成,不表示包能运行。Blankly 的 __init__.py 会无条件导入指标模块,而指标模块依赖一个 C 扩展;这个扩展与 numpy 2.x 的 ABI 不兼容,所以只有真正导入时才会报错。判断安装是否可用,唯一可靠的检查是执行一次 import。
搜这个报错时该搜 tulipy 还是 newnewtulipy?
两个都试。PyPI 上的包名是 newnewtulipy,但它安装后的导入命名空间是 tulipy,堆栈里显示的也是 tulipy。这也是为什么很多人搜不到答案——报错信息里的名字与包管理器里的名字不一致。
只钉 numpy<2 就够了吗?pandas 呢?
本机实测中,解析结果是 pandas 3.0.6 搭配 numpy 1.26.4,四个子模块导入与一次离线回测都正常完成,所以本次没有额外钉 pandas。但要提醒:这套组合不在官方 CI 覆盖范围内(官方最后发行于 2023 年,当时 pandas 3.x 还不存在),所以它是「实测可用」而非「官方保证可用」。如果你的场景用到较多 pandas API,建议把 pandas 也一起钉住并跑一遍自己的用例。
能不能把 --no-deps 用上,手动只装需要的部分?
不建议作为首选。因为 blankly/__init__.py 会导入交易所接口、指标、部署模块等一大批子模块,缺任何一个都会在导入阶段失败,手动裁剪依赖的成本高于直接钉一个 numpy 上限。如果你的目标是「只要指标函数」,那更合理的做法是直接使用提供同功能指标的其它库,而不是从 Blankly 里拆。
为什么 blankly --help 也会报同一个错?
因为 --help 需要先导入 blankly 包才能进入参数解析,而导入过程本身就在指标模块处中断了。所以在这个版本上,「CLI 能不能用」和「包能不能导入」是同一个问题,修好依赖后两者会同时恢复。
装好之后第一个该跑什么?
建议先跑不需要 API 密钥的离线回测:用 KeylessExchange 加一个自己准备的六列 CSV,确认整条回测链路能走通,再考虑接交易所。这样可以把「代码问题」和「密钥/权限问题」分开排查。具体步骤见首个离线回测页,数据格式要求见 Keyless 与数据读取器页。