Make distutils look for numpy header files in the correct place

后端 未结 3 651
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-11-28 05:44

In my installation, numpy\'s arrayobject.h is located at …/site-packages/numpy/core/include/numpy/arrayobject.h. I wrote a trivial Cython script t

相关标签:
3条回答
  • 2020-11-28 06:12

    For anyone not using Cython, a slight modification of R_Beagrie's solution without that dependency is if you simply import build_ext from distutils.command.build_ext instead of Cython.

    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
    )
    
    0 讨论(0)
  • 2020-11-28 06:25

    The answer given by @vebjorn-ljosa is correct, but it causes problems when used in conjunction with install_requires=['numpy']. In this situation, your setup.py needs to import numpy, which will cause an error if you try to pip install your project without running pip install numpy first.

    If your project depends on numpy, and you want numpy to be installed automatically as a dependency, you need to set include_dirs only when your extensions are actually being built. You can do this by subclassing 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
    )
    

    And you can use a similar trick to add cython as an automatically installed dependency:

    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
    )
    

    Note: these approaches only work with pip install .. They won't work for python setup.py install or python setup.py develop as in these commands cause dependencies to be installed after your project, rather than before.

    0 讨论(0)
  • 2020-11-28 06:27

    Use 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"],
                                      include_dirs=[get_numpy_include()])]   # <---- New argument
    
    setup(
      name = 'Hello world app',
      cmdclass = {'build_ext': build_ext},       
      ext_modules = ext_modules
    )
    
    0 讨论(0)
提交回复
热议问题