Pandas 2.2.3 版本详解:首个完整兼容 Python 3.13 的发布版与表达式求值 Bug 修复
【免费下载链接】pandasFlexible and powerful data analysis / manipulation library for Python, providing labeled data structures similar to R data.frame objects, statistical functions, and much more项目地址: https://gitcode.com/gh_mirrors/pa/pandas
Pandas 2.2.3(发布于 2024 年 9 月 20 日)是 pandas 2.2 系列的一个维护性补丁版本,其核心价值在于:它是 pandas 首个与 Python 3.13 全面兼容的正式版本,同时修复了eval/query中复数(complex)除法丢失虚部的历史性 Bug,并为 numpy 2.1 做了兼容性微调。本文以官方发布说明(doc/source/whatsnew/v2.2.3.rst)为骨架,结合仓库源码与测试用例,逐条剖析该版本的每一项变更,帮助你判断是否需要升级、升级后行为有何变化,以及如何验证。
版本概览:一次小步快跑的维护性更新
从变更规模上看,2.2.3 属于典型的补丁版本:没有新增 API,没有弃用(deprecation)变更,也没有破坏性行为调整,全部改动集中在"兼容性"与"正确性"两个方向:
- Python 3.13 全面兼容:首个官方支持 Python 3.13 的 pandas 版本,同时提供普通与 free-threaded(无 GIL)两种 CPython 3.13 的 wheel;
- 表达式求值正确性修复:
eval对 complex 类型执行除法/时不再丢失虚部; - numpy 2.1 兼容性微调:针对 numpy 2.1 的一处小问题修复;
- 发布产物完整性修复:第三方依赖的许可证文件重新被打包进 wheel。
完整变更列表以 doc/source/whatsnew/v2.2.3.rst 为准,各版本历史见 doc/source/whatsnew/index.rst。
Python 3.13 兼容:从"预告"到"正式"
发布说明明确写道:"Pandas 2.2.3 is the first version of pandas that is generally compatible with the upcoming Python 3.13"——即 2.2.3 是第一个与 Python 3.13 普遍兼容的 pandas 版本。
值得关注的是其中两个细节:
- 普通与 free-threaded 双 wheel:该版本为 Python 3.13 同时上传了两种构建产物——标准 CPython 3.13 wheel,以及 free-threaded(无 GIL)实验性构建的 wheel。后者对应 CPython 3.13 中可选的
--disable-gil构建模式,pandas 在该模式下通过_cpu.py等模块的运行时探测来适配线程与 GIL 相关的行为(见 pandas/compat/_cpu.py 及 pandas/compat/_constants.py)。 - 兼容性边界:"generally compatible"意味着 2.2.3 完成的是常规使用场景下的适配,而非对 Python 3.13 所有实验性特性(如 free-threaded 模式下的完整并行语义)的最终承诺。若在 3.13 下发现新问题,应通过官方 issue tracker 提交。
如何验证安装环境
升级后在 Python 3.13 环境下执行以下检查,可以快速确认版本与依赖状态:
import pandas as pd import sys print(sys.version) # 应显示 3.13.x print(pd.__version__) # 应显示 2.2.3 print(pd.show_versions()) # 打印 numpy、numexpr 等依赖的完整版本矩阵依赖矩阵的打印逻辑位于 pandas/util/_print_versions.py,升级后建议用其确认numpy、numexpr、bottleneck等关键依赖版本与 pandas 2.2.3 的搭配是否在预期范围内。
Bug 修复(一):eval中复数除法丢失虚部
这是本次发布最有技术含量的一项修复,对应 issue GH#21374。
问题现象
在此之前,通过eval(或DataFrame.eval/DataFrame.query)对 complex 类型数据执行除法/时,结果会丢失虚部。仓库测试 pandas/tests/frame/test_query_eval.py 精确复现了该场景:
def test_complex_eval(self, engine, parser): # GH#21374 df = pd.DataFrame({"a": [1 + 2j], "b": [1 + 1j]}) result = df.eval("a/b", engine=engine, parser=parser) expected = pd.Series([1.5 + 0.5j]) tm.assert_series_equal(result, expected)即(1 + 2j) / (1 + 1j)的数学结果是1.5 + 0.5j,修复前在部分引擎路径下只返回实部。
底层原理:算术运算符的注册表
eval的表达式解析与求值链路位于 pandas/core/computation/expr.py 与 pandas/core/computation/ops.py。其中除法运算符的映射定义在 pandas/core/computation/ops.py:
ARITH_OPS_SYMS = ("+", "-", "*", "/", "**", "//", "%") _arith_ops_funcs = ( operator.add, operator.sub, operator.mul, operator.truediv, # "/" 直接映射到 Python 原生 operator.truediv operator.pow, operator.floordiv, operator.mod, )修复的核心是保证/在所有引擎与解析器组合下都严格走operator.truediv的复数语义,而不是在类型提升(upcasting)或底层数值库路径中退化为只保留实部的运算。配套的回归测试覆盖了两层:
- 语法层(complex 除法语义):即上面的
test_complex_eval,同时以engine × parser组合参数化运行; - 类型提升层:
TestTypeCasting类(pandas/tests/computation/test_eval.py)对["+", "-", "*", "**", "/"]全部算术符逐一验证,在complex64/complex128下断言df.values.dtype == dtype且结果与原生 Pythoneval一致,确保除法不再破坏复数的 dtype 与虚部。
注意测试中一处细节:numexpr引擎在complex64上存在上游的 upcast 问题(numexpr issue #492),因此该组合被标记为xfail。这也解释了为什么复数除法修复主要作用于python引擎路径——若你同时安装了 numexpr 且使用 complex 数据,仍建议显式指定engine="python"。
实操验证
在你的环境中用以下脚本即可一键验证修复是否生效:
import pandas as pd import numpy as np df = pd.DataFrame({"a": [1 + 2j, 3 + 4j], "b": [1 + 1j, 1 - 1j]}) # 修复前:虚部丢失;修复后:得到 1.5+0.5j 与 -0.5+3.5j print(df.eval("a / b", engine="python")) # 与 NumPy/Python 原生结果对齐检查 print(df["a"].to_numpy() / df["b"].to_numpy())若两行输出一致(虚部完整保留),说明该 Bug 已在当前环境中修复。
Bug 修复(二):numpy 2.1 兼容性微调
发布说明中另一项修复为"Minor fixes for numpy 2.1 compatibility"(对应 GH#59444)。这是 numpy 2.x 大版本迁移工作(自 pandas 2.2 系列持续推进)的延续:
- pandas 2.2.x 系列通过 pandas/compat/numpy/function.py 与 pandas/compat/numpy/init.py 等适配层,对 numpy 2.0 引入的 API 变更(如部分函数别名、dtype 行为调整)做兼容;
- 2.2.3 在此基础上针对 numpy 2.1 做了少量修正,属于"微调"级别(minor fixes),不影响公开 API。
对于普通用户,升级 numpy 至 2.1.x 后若遇到与 pandas 相关的告警或异常,升级到 2.2.3 即可覆盖绝大多数场景;若仍有问题,应通过 pandas/issues 提交包含pd.show_versions()输出的完整报告。
其他变更:wheel 内第三方许可证回归
发布说明的 "Other" 部分只有一条:"Missing licenses for 3rd party dependencies were added back into the wheels"(对应 GH#58632)。
pandas 的 wheel 构建中会捆绑若干第三方 C/C++ 库(如日期解析用的 dateutil 片段、Excel 读取依赖、numpy 片段、XSIMD 等),这些库的许可证文本此前在部分 wheel 产物中缺失,2.2.3 将其重新补回。仓库中的 LICENSES 目录集中存放了这些第三方许可证文本,包括DATEUTIL_LICENSE、NUMPY_LICENSE、XSIMD_LICENSE、BOTTLENECK_LICENCE、HAVEN_LICENSE、MUSL_LICENSE等十余份文件,可作为核对打包清单的参照。
对普通使用者的实际影响很小,主要受益方是需要做合规审计、将 pandas wheel 再分发的企业用户——升级后可在site-packages/pandas的LICENSES目录中确认许可证文件齐全。
升级建议与注意事项
| 关注点 | 结论 |
|---|---|
| 是否破坏性变更 | 否,纯维护性补丁,API 无变化 |
| 最值得升级的理由 | 需要 Python 3.13 环境;使用eval/query处理 complex 数据 |
| Python 版本前提 | 该版本官方支持的 Python 版本区间与 2.2 系列一致,3.13 支持为本版本新增 |
| 复数除法引擎选择 | complex 数据建议显式engine="python",规避 numexpr 的 upcast 限制 |
| 合规要求 | 升级后核对 wheel 内第三方许可证是否齐全 |
升级命令(任选其一,按实际环境):
pip install --upgrade pandas==2.2.3 # 或使用 conda conda install pandas=2.2.3升级完成后,建议运行仓库自带的回归测试子集做冒烟验证(需要已 clone 仓库并具备测试依赖):
# 验证 complex eval 修复与类型提升回归测试 python -m pytest pandas/tests/frame/test_query_eval.py -k "complex" python -m pytest pandas/tests/computation/test_eval.py -k "TypeCasting"以上测试文件路径与 GH#21374 回归用例一一对应,通过即代表该修复在你的环境中正确生效。结合 doc/source/whatsnew/v2.2.3.rst 的完整变更清单,你可以据此做出清晰的升级决策。
【免费下载链接】pandasFlexible and powerful data analysis / manipulation library for Python, providing labeled data structures similar to R data.frame objects, statistical functions, and much more项目地址: https://gitcode.com/gh_mirrors/pa/pandas
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考