让distutils在正确的位置寻找numpy头文件
在我的安装中,numpy的arrayobject.h
位于…/site-packages/numpy/core/include/numpy/arrayobject.h
。 我写了一个简单的使用numpy的Cython脚本:
cimport numpy as np def say_hello_to(name): print("Hello %s!" % name)
我也有以下distutils setup.py
(从Cython用户指南复制):
from distutils.core import setup from distutils.extension import Extension from Cython.Distutils import build_ext ext_modules = [Extension("hello", ["hello.pyx"])] setup( name = 'Hello world app', cmdclass = {'build_ext': build_ext}, ext_modules = ext_modules )
当我尝试使用python setup.py build_ext --inplace
构build时,Cython尝试执行以下操作:
gcc -fno-strict-aliasing -Wno-long-double -no-cpp-precomp -mno-fused-madd \ -fno-common -dynamic -DNDEBUG -g -Os -Wall -Wstrict-prototypes -DMACOSX \ -I/usr/include/ffi -DENABLE_DTRACE -arch i386 -arch ppc -pipe \ -I/System/Library/Frameworks/Python.framework/Versions/2.5/include/python2.5 \ -c hello.c -o build/temp.macosx-10.5-i386-2.5/hello.o
可以预见的是,这无法findarrayobject.h
。 我怎样才能让distutils使用numpy包含文件的正确位置(而不是让用户定义$ CFLAGS)?
使用numpy.get_include()
:
from distutils.core import setup from distutils.extension import Extension from Cython.Distutils import build_ext import numpy as np # <---- New line ext_modules = [Extension("hello", ["hello.pyx"])] setup( name = 'Hello world app', cmdclass = {'build_ext': build_ext}, include_dirs = [np.get_include()], # <---- New line ext_modules = ext_modules )
@ vebjorn-ljosa给出的答案是正确的,但是当与install_requires=['numpy']
结合使用时,会导致问题。 在这种情况下,您的setup.py需要导入numpy,如果您尝试在没有首先运行pip install numpy
情况下点击pip install
项目,将会导致错误。
如果您的项目依赖于numpy,并且您希望numpy作为依赖项自动安装,则只有在实际构build扩展时才需要设置include_dirs。 你可以通过build_ext
来做到这build_ext
:
from distutils.core import setup from distutils.extension import Extension from Cython.Distutils import build_ext class CustomBuildExtCommand(build_ext): """build_ext command for use when numpy headers are needed.""" def run(self): # Import numpy here, only when headers are needed import numpy # Add numpy headers to include_dirs self.include_dirs.append(numpy.get_include()) # Call original build_ext command build_ext.run(self) ext_modules = [Extension("hello", ["hello.pyx"])] setup( name = 'Hello world app', cmdclass = {'build_ext': CustomBuildExtCommand}, install_requires=['numpy'], ext_modules = ext_modules )
你也可以使用类似的技巧将cython添加为自动安装的依赖项:
from distutils.core import setup from distutils.extension import Extension try: from Cython.setuptools import build_ext except: # If we couldn't import Cython, use the normal setuptools # and look for a pre-compiled .c file instead of a .pyx file from setuptools.command.build_ext import build_ext ext_modules = [Extension("hello", ["hello.c"])] else: # If we successfully imported Cython, look for a .pyx file ext_modules = [Extension("hello", ["hello.pyx"])] class CustomBuildExtCommand(build_ext): """build_ext command for use when numpy headers are needed.""" def run(self): # Import numpy here, only when headers are needed import numpy # Add numpy headers to include_dirs self.include_dirs.append(numpy.get_include()) # Call original build_ext command build_ext.run(self) setup( name = 'Hello world app', cmdclass = {'build_ext': CustomBuildExtCommand}, install_requires=['cython', 'numpy'], ext_modules = ext_modules )
注意:这些方法只适用于pip install .
。 他们不会为python setup.py install
或python setup.py develop
因为在这些命令中会导致依赖项被安装在项目之后,而不是之前。