事情的缘由是我要在新的lxd虚拟机环境做一些数字病理图像分析的任务,要使用到HistomicsTK 这个包,但今天重点要将的不是这个包,所以我就不再进行介绍。一个奇怪的问题就是在虚拟机直接pip安装这个包是一切正常的:
python -m pip install histomicstk --find-links https://girder.github.io/large_image_wheels
但在import的时候就会引起“浮点数例外 (核心已转储)”的错误,但在别的服务器上是没这个问题的。由于尝试了几次环境的安装都解决不了这个问题,我就找回旧版本的代码(大概是1.1.0)自己复制过到python的site-package目录了事。由于之前我保存的旧代码是基于python3.6编译的,现在已经是使用python3.8了,代码中引用的一些原来cpython编译的脚本就不能用,强行要会报错,比如:
from _trace_object_boundaries_cython import _trace_object_boundaries_cython
:219: RuntimeWarning: compiletime version 3.6 of module 'HistomicsTK.histomicstk.segmentation.label._trace_object_boundaries_cython' does not match runtime version 3.8
原来的_trace_object_boundaries_cython方法是用cpython写的pyx文本,因此需要自己手工重新要cpython编译一次。随便网上找到一个方法,按照demo我是这样写的setup.py:
from setuptools import setup
from Cython.Build import cythonize
setup(
ext_modules=cythonize("_trace_object_boundaries_cython.pyx")
)
然后是这样执行:
python setup.py build_ext --inplace
但实际这样执行,如果有用到numpy的话是会报错的:
_trace_object_boundaries_cython.c:623:10: fatal error: numpy/arrayobject.h: 没有那个文件或目录
623 | #include "numpy/arrayobject.h"
| ^~~~~~~~~~~~~~~~~~~~~
compilation terminated.
error: command 'gcc' failed with exit status 1
虽然当前的python环境肯定已经安装numpy了,但使用cpython进行编译的时候是需要系统有相关的库,所以可以用以下命令安装:
sudo apt-get install python-numpy
这个报错就算是解决。之后继续编译,有可能会遇到本文标题说到的错误,比如:
/usr/include/numpy/npy_1_7_deprecated_api.h:17:2: warning: #warning "Using deprecated NumPy API, disable it with " "#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION" [-Wcpp]
17 | #warning "Using deprecated NumPy API, disable it with " \
| ^~~~~~~
_trace_object_boundaries_cython.c:702:10: fatal error: ios: 没有那个文件或目录
702 | #include "ios"
| ^~~~~
compilation terminated.
error: command '/usr/bin/gcc' failed with exit code 1
这个目录我在百度搜索了一圈,唯一找到一篇的回答还是非公开访问的,于是使用其他搜索引擎用英文搜,终于在https://stackoverflow.com/questions/53471655/compiling-cython-with-gcc-no-such-file-or-directory-from-include-ios
找到一个可行的方案,原来是要在上述setup.py中增加 language="c++" ,将其代码改写如下:
from setuptools import setup
from Cython.Build import cythonize
from distutils.extension import Extension
import numpy
extensions = [
Extension("_trace_object_boundaries_cython", sources=["_trace_object_boundaries_cython.pyx"], include_dirs=[numpy.get_include()], extra_compile_args=["-O3"], language="c++")
]
setup(
name="_trace_object_boundaries_cython",
ext_modules = cythonize(extensions),
)
依旧是使用上述语句进行进行编译,这次终于提示成功并生成对应的so文件:
_trace_object_boundaries_cython.cpp: In function ‘PyObject* __pyx_pf_31_trace_object_boundaries_cython_4_isbf(PyObject*, __Pyx_memviewslice, __Pyx_memviewslice, __Pyx_memviewslice, __Pyx_memviewslice, int, int, float)’:
_trace_object_boundaries_cython.cpp:6753:43: warning: comparison of integer expressions of different signedness: ‘long int’ and ‘std::vector::size_type’ {aka ‘long unsigned int’} [-Wsign-compare]
6753 | for (__pyx_t_8 = 0; __pyx_t_8 < __pyx_t_20; __pyx_t_8+=1) {
| ~~~~~~~~~~^~~~~~~~~~~~
copying build/lib.linux-x86_64-3.8/_trace_object_boundaries_cython.cpython-38-x86_64-linux-gnu.so ->
这个文件亲测import是没问题的。至此,问题得到解决,总的来说,使用cython包编译会出一些奇怪的依赖问题,尽量不要对太复杂的业务功能代码做这个操作,只考虑核心的计算功能用才使用cpython进行编译(提数是重要的,保护脚本文件其实我觉得没那么必要)