问题
我们的一个程序,主程序是基于c++编写,在主程序中通过ypbind11调用python从而实现可以通过python编写脚本,python通过numpy把数据返回给c++,最近打包的镜像突然发现c++侧无法正常拿到数据了,通过debug发现pybind11侧从python结构里面拿到的数据的itemsize是0,去查看了pybind11的更新发现是因为我们的pybind11版本和numpy2.0不兼容了,需要升级更新的pybind11才能兼容numpy2.0.
这里我们在作镜像的时候会安装numpy依赖,但是因为我们在requirement.txt中只指定了最小版本,没有指定最大版本,所以当安装的numpy是2.0的时候,就会有问题。
pybind11怎么兼容的
可以看到在新版本的pybind11中,https://github.com/pybind/pybind11/blob/master/include/pybind11/numpy.h里面已经同时包含了numpy的1.0和2.0的对象部署声明:
/* NumPy 1 proxy (always includes legacy fields) */
struct PyArrayDescr1_Proxy {
PyObject_HEAD
PyObject *typeobj;
char kind;
char type;
char byteorder;
char flags;
int type_num;
int elsize;
int alignment;
char *subarray;
PyObject *fields;
PyObject *names;
};
struct PyArrayDescr_Proxy {
PyObject_HEAD
PyObject *typeobj;
char kind;
char type;
char byteorder;
char _former_flags;
int type_num;
/* Additional fields are NumPy version specific. */
};
/* NumPy 2 proxy, including legacy fields */
struct PyArrayDescr2_Proxy {
PyObject_HEAD
PyObject *typeobj;
char kind;
char type;
char byteorder;
char _former_flags;
int type_num;
std::uint64_t flags;
ssize_t elsize;
ssize_t alignment;
PyObject *metadata;
Py_hash_t hash;
void *reserved_null[2];
/* The following fields only exist if 0 <= type_num < 2056 */
char *subarray;
PyObject *fields;
PyObject *names;
};
struct PyArray_Proxy {
PyObject_HEAD
char *data;
int nd;
ssize_t *dimensions;
ssize_t *strides;
PyObject *base;
PyObject *descr;
int flags;
};
并且在涉及到不兼容的地方都加入了numpy的版本判断。
ssize_t itemsize() const {
if (detail::npy_api::get().PyArray_RUNTIME_VERSION_ < 0x12) {
return detail::array_descriptor1_proxy(m_ptr)->elsize;
}
return detail::array_descriptor2_proxy(m_ptr)->elsize;
}
解决方案
所以这里的解决方案有两种:
- 升级pybind11版本,重新编译程序。
- 锁定numpy版本到2.0以下。
教训
在不确定的情况下,python的依赖在测试通过后,最好锁定版本,避免出现因为版本不兼容导致的问题。
有兴趣请关注我的微信公众号:码哥日常,码农和码农娃的日常经验分享。
pybind11与numpy版本兼容问题
4095

被折叠的 条评论
为什么被折叠?



