CPython编译的一些trick (No such file or directory from #include “ios“)

HistomicsTK

事情的缘由是我要在新的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进行编译(提数是重要的,保护脚本文件其实我觉得没那么必要)

你可能感兴趣的:(python,python,图像处理)