Blankly / 安装与依赖边界

装了不等于能用:Blankly 在 Python 3.11 上装完就 import 失败

README 的安装说明只有两行:pip install blankly,然后 blankly init。这两步在 2026 年都还执行得下去——但中间缺了一环:装完之后 import blankly 会直接抛出 numpy 的二进制不兼容错误,连 blankly --help 都进不去。这一页把完整报错、依赖链成因和实测可用的处置顺序摊开写,你可以照着一步步复现。

实测环境:Python 3.11.9 / Windows实测版本:1.18.25b0日志保留原始输出本站未实机交易
① pip install成功,解析到 numpy 2.4.6 / pandas 3.0.6
② import 报错ValueError: numpy.dtype size changed 96 vs 88
③ 钉 numpy<2降到 1.26.4 后 import 全部 OK
④ Python 3.12+依赖无对应轮子,需本地编译
依赖兼容判定示意(依据 2026-09-21 本机 Python 3.11 实测整理,非官方排查流程)。节点①②③在本页有完整原始输出,节点④的依据是 PyPI 上的轮子标签覆盖范围。
实测记录

怎么完整复现?每一步的命令与退出码

下表是本机在 2026-09-21 实际执行的命令序列。退出码 0 表示命令成功,所以「安装成功」和「导入失败」这两件看似矛盾的事可以同时成立。

步骤执行的命令退出码结果
1. 建虚拟环境python -m venv v0成功
2. 升级 pipv\Scripts\python -m pip install --upgrade pip --quiet0成功
3. 按 README 安装v\Scripts\python -m pip install blankly0成功,下载 blankly-1.18.25b0-py3-none-any.whl
4. 查看解析结果v\Scripts\python -m pip freeze0得到 numpy 2.4.6、pandas 3.0.6 等 47 个包
5. 导入包v\Scripts\python -c "import blankly"0抛异常:ValueError: numpy.dtype size changed
6. 调 CLIv\Scripts\python -m blankly --help1失败,同一个异常在导入阶段就中断
7. 钉住 numpyv\Scripts\python -m pip install "numpy<2"0numpy 降到 1.26.4
8. 再次导入v\Scripts\python -c "import blankly"0成功,四个子模块全部 OK
9. 再次调 CLIv\Scripts\python -m blankly --help0成功,列出 initkey
第 6 步为什么值得单独列出来:很多人装完会先跑 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 20import tulipy as ti报错来自第三方 C 扩展,不是 Blankly 自己的 Python 代码
tulipy/__init__.pytulipy\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-07README 与 classifiers 只列到 Python 3.103.12+ 连 newnewtulipy 轮子都没有,需本地编译工具链
alpaca-trade-api2024-01(最后上传)已是上游弃用的旧客户端它把 urllib3 钉在 <2,又会与其它包互相约束
一句话总结:Blankly 声明的依赖没有上限,但它的一个关键依赖已经不再产出新轮子。只要 pip 从网上解析,就会自动踩到 numpy 2.x,所以这个故障是可预期、可复现的,不是环境碰巧的问题。
处置方案

该选哪条处置路线?按 Python 版本与环境干净度

本机实测走的是路线 1。路线 2 和 3 是针对不同约束的替代方案,本站没有全部实测,因此会明确标注哪些是实测、哪些是依据轮子覆盖范围的推断。

方案具体做法适用场景本站验证状态
方案 1:钉 numpy 上限pip install "numpy<2" 再装 blankly,或把 numpy<2 写进自己的 requirements.txtPython 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

每一步都给出真实命令、它做什么,以及你应该看到什么。如果某一步的输出与预期不同,先停下来核对,不要往下走。

  1. 建一个独立虚拟环境

    命令:python -m venv v(Windows 激活用 v\Scripts\activate,macOS/Linux 用 source v/bin/activate)。独立环境的价值在于:这条依赖链需要钉死 numpy 版本,如果装进全局环境,会影响你机器上其它项目。预期输出:命令无输出即成功,目录下出现 v/

  2. 先钉住 numpy 上限,再装 Blankly

    命令:pip install "numpy<2" 然后 pip install blankly。顺序可以互换,但先钉上限能避免中间态出现一个装好却用不了的版本。预期输出:先看到 numpy 解析到 1.26.x,再看到 blankly-1.18.25b0-py3-none-any.whl 被安装。

  3. 验证导入而不是只验证安装

    命令:python -c "import blankly, blankly.indicators, blankly.metrics; print('import ok')"。这一步是整页的核心——pip install 的退出码不能证明包可用。预期输出:import ok

  4. 验证 CLI

    命令:python -m blankly --help。预期输出:列出两个子命令 initkey。如果你看到的是 login/deploy,说明你用的不是这个发行版,请以实际输出为准。

  5. 把约束固化下来

    命令: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_64macosx_11_0_arm64 轮子依据轮子清单推断可行,本站未实测
Linux(x86_64)未单独声明manylinux2014_x86_64 轮子依据轮子清单推断可行,本站未实测
注意「官方声明」与「实际可行」的差别:3.11 不在官方声明里,但依赖轮子是齐的,所以实测能跑通;反过来,官方声明的 3.10 如果 numpy 解析到 2.x,同样会报同一个错。判断依据应该看轮子标签,而不是看支持声明。
FAQ

安装与依赖相关的高频问题

回答基于 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 与数据读取器页。

下一步:怎么用离线数据验证整条链路?

依赖修好之后,先别急着接交易所。用 Keyless 模式和一份本地价格文件,可以在没有任何密钥的情况下确认回测链路完整可用。