DEBUG.WIKI
野草云;香港 200Mbps 峰值;不限月流量 · BGP VPS;查看套餐 →
雨云;给项目一台云服务器
RackNerd;$21.99/年 · 1GB KVM

savez_compressed 展开数组字典,mypy 却要求 bool

dict[str, NDArray] 没有排除 allow_pickle 保留键。固定格式用 TypedDict 表达键集合,动态数组名则明确参数冲突与对象保存策略。

np.savez_compressed("data.npz", **arrays) 的字典值全是 ndarray,mypy 或 ty 却说其中一个参数应该是 bool。看到错误指向 allow_pickle 时,先看字典的键类型,别急着给所有数组加类型忽略。

NumPy 2.5.4 的声明同时包含显式参数 allow_pickle: bool 和接收数组的 **kwds。dict[str, NDArray[...]] 只约束值是数组,没有排除键名 allow_pickle;类型检查器因此必须考虑这个键也可能被展开成显式布尔参数。

这不是把数组改成布尔值才能保存。运行中确实有这个保留键时,它也不能同时充当任意数组名称,应该先解决命名冲突。

固定字段用 TypedDict 表达实际键集合

文件的数组名本来固定时,可让类型声明与格式约定一致:

from typing import TypedDict
import numpy as np
from numpy.typing import NDArray

class Arrays(TypedDict):
    positions: NDArray[np.float64]
    weights: NDArray[np.float64]

arrays: Arrays = {
    "positions": np.array([1.0, 2.0], dtype=np.float64),
    "weights": np.array([0.25, 0.75], dtype=np.float64),
}
np.savez_compressed("data.npz", **arrays)

这段示例会写出文件,同名文件可能被覆盖,路径应换成任务专用的新输出位置;已有结果先保留原件,读回验收后再按项目流程切换,撤回时恢复原文件与读取配置。TypedDict 不是运行时校验器;外部字典不能仅通过一个类型转换就变成可信的固定格式,入口仍需核对键、dtype 和形状。

动态键则明确保留参数与保存策略

动态数组名需要先拒绝与调用参数冲突的名称,再决定是否显式给出 allow_pickle。对确认全是数值、无需对象 pickle 的文件,可以将 allow_pickle=False 作为明确的保存策略;显式参数也能帮助检查器区分这部分调用意图。

但不要为了消掉类型提示就改变已有对象数组的保存规则。对象数组在禁用 pickle 后应被拒绝,不能把保存失败吞掉,或自动转字符串再声称数据完整。反过来,开启 pickle 也不是修复 typing 的通用办法,读取这类文件需要与原格式的可信数据边界一致。

具体错误有 NumPy 2.5.4、mypy 2.4.0 和 ty 0.0.89 的对应记录。当前声明确实存在保留参数,不能承诺换一个检查器就能让任意动态字典满足它。

修改后先运行项目原来的静态检查,再在允许写文件的隔离目录保存并读回一个代表性样本,核对数组名称、dtype、形状和值。检查通过只说明调用签名能确定;文件成功生成也不保证接收方按预期读取了全部数组。