numpy 2.x scalar types np.float32 and others are no longer convertible
还没有人认领这个 Issue。
评估
调研方向
先从 test_module.cpp 中的复现程序和列出的 Python 标量转换示例开始,然后跟踪 Boost.Python 为 double、float、int 和 long 提供的内置 rvalue 转换器,尤其是其中的 PyFloat_Check 和 PyLong_Check 路径。完成的标准是:复现程序无需显式进行 Python 转换即可接受 issue 中描述的 NumPy 标量类型,同时保留对内置值的现有行为。
由索引模型根据 Issue 内容生成。
描述
Summary
In NumPy 2.0, scalar types such as np.float32, np.int32, and np.int64 no longer subclass Python's built-in float or int (per
NEP 51). Boost.Python's built-in rvalue converters for C++ double, float, int, and long use PyFloat_Check / PyLong_Check, which return false for these NumPy scalars. The result is ArgumentError: Python argument types did not match C++ signature for any Boost.Python-wrapped function that previously accepted NumPy scalars via implicit conversion.
np.float64 is unaffected because it still subclasses Python float.
Reproducing
Put the following in test_module.cpp:
#include <boost/python.hpp>
double take_double(double x) { return x; }
float take_float(float x) { return x; }
int take_int(int x) { return x; }
long take_long(long x) { return x; }
BOOST_PYTHON_MODULE(test_module)
{
using namespace boost::python;
def("take_double", take_double);
def("take_float", take_float);
def("take_int", take_int);
def("take_long", take_long);
}
Then do:
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
bash Miniconda3-latest-Linux-x86_64.sh -b -p $PWD/mc3
source mc3/etc/profile.d/conda.sh
conda create -y -p $PWD/env -c conda-forge python=3.11 "numpy>=2.0" libboost-python-devel gxx_linux-64
conda activate $PWD/env
$CXX -shared -fPIC -o test_module.so test_module.cpp -Ienv/include/python3.11 -Ienv/include -Lenv/lib -lboost_python311 -Wl,-rpath,env/lib
python -c "import numpy as np; import test_module; test_module.take_double(np.float32(1.5))"
The python script at the bottom of the issue gives some more types that don't convert.
Workaround
Users can explicitly convert before passing to Boost.Python:
func(float(np.float32(1.5))) # works
func(int(np.int32(42))) # works
func(np.float32(1.5).item()) # also works
I have implemented this in a few places and I'm sure many others have as well. See https://github.com/cctbx/cctbx_project/issues/1084
Longer python reproducer
import numpy as np
import test_module
# Show which numpy scalars still subclass builtins (the root cause)
for np_type in [np.float64, np.float32, np.float16,
np.int64, np.int32, np.int16, np.int8]:
builtin = float if np.issubdtype(np_type, np.floating) else int
print("issubclass(%s, %s): %s" % (
np_type.__name__, builtin.__name__, issubclass(np_type, builtin)))
print()
scalar_values = [
np.float64(1.5),
np.float32(1.5),
np.float16(1.5),
np.int64(42),
np.int32(42),
np.int16(42),
np.int8(42),
np.uint64(42),
np.uint32(42),
]
functions = [
(test_module.take_double, "take_double"),
(test_module.take_float, "take_float"),
(test_module.take_int, "take_int"),
(test_module.take_long, "take_long"),
]
for func, func_name in functions:
for scalar in scalar_values:
try:
result = func(scalar)
print("Pass", func_name, type(scalar))
except Exception as e:
print("Fail", func_name, type(scalar))
- 主要语言
- C++
- 星标
- 537
- 派生
- 223
- 平均合并
- 11 小时 22 分钟
- 30 天内合并 PR
- 2
贡献指南
这个仓库没有索引到贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
boostorg/python 的其他 Issue
-
难度 1/5 1 小时以内 新手友好度 84/100
-
难度 2/5 1-3 小时 新手友好度 68/100
-
难度 2/5 1-3 小时 新手友好度 64/100
-
BoostDetectToolset-1.90.0.cmake file not found in an include() call in boost_python-config.cmake 未关闭
难度 3/5 1-2 天 新手友好度 48/100
-
难度 4/5 3-5 天 新手友好度 25/100
相似的 Issue
-
难度 1/5 1 小时以内 新手友好度 90/100
AXERA-TECH/ax-llm#77 ·
-
难度 1/5 1 小时以内 新手友好度 90/100
games-on-whales/wolf#509 ·
-
难度 2/5 1-3 小时 新手友好度 74/100
-
bug-unconfirmed
难度 2/5 1-3 小时 新手友好度 76/100
-
难度 2/5 1-3 小时 新手友好度 74/100
NVIDIA/cuda-samples#453 ·