代码之家  ›  专栏  ›  技术社区  ›  Vebjorn Ljosa

使distutils在正确的位置查找numpy头文件

  •  41
  • Vebjorn Ljosa  · 技术社区  · 15 年前

    在我的装置中,numpy's 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 user guide ):

    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 ,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
    

    可想而知,这并没有找到 数组对象H . 如何使distuils使用numpy include文件的正确位置(而不让用户定义$cflags)?

    3 回复  |  直到 6 年前
        1
  •  62
  •   Vebjorn Ljosa    15 年前

    使用 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
    )
    
        2
  •  21
  •   R_Beagrie    8 年前

    @vebjorn ljosa给出的答案是正确的,但与 install_requires=['numpy'] . 在这种情况下,您的setup.py需要导入numpy,如果尝试导入,这将导致错误。 pip install 你的项目没有运行 pip install numpy 第一。

    如果您的项目依赖于numpy,并且您希望将numpy作为依赖项自动安装,则只有在实际构建扩展时才需要设置include dirs。您可以通过子类化来实现这一点。 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 在这些命令中,会导致依赖项在项目之后而不是之前安装。

        3
  •  0
  •   tgbrooks    6 年前

    对于不使用cython的任何人来说,在没有依赖关系的情况下,对r_-beagrie的解决方案做一个细微的修改就是从distutils.command.build-ext而不是cython导入build-ext。

    from distutils.core import setup
    from distutils.extension import Extension
    from distutils.command.build_ext 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.c"])]
    
    setup(
      name = 'Hello world app',
      cmdclass = {'build_ext': CustomBuildExtCommand},
      install_requires=['numpy'],
      ext_modules = ext_modules
    )