Domanda

Nella mia installazione, arrayobject.h di NumPy si trova a …/site-packages/numpy/core/include/numpy/arrayobject.h. Ho scritto una sceneggiatura banale Cython che usi NumPy:

cimport numpy as np

def say_hello_to(name):
    print("Hello %s!" % name)

Ho anche il seguente distutils setup.py (copiato dal guida 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
)

Quando provo a costruire con python setup.py build_ext --inplace, Cython cerca di fare quanto segue:

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

Come era prevedibile, questo non riesce a trovare arrayobject.h. Come posso fare distutils utilizzare il percorso corretto di NumPy includere file (senza che l'utente definisce $ CFLAGS)?

È stato utile?

Soluzione

Usa 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
)

Altri suggerimenti

La risposta in @ Vebjørn-ljosa è corretto, ma causa problemi quando usato in combinazione con install_requires=['numpy']. In questa situazione, le vostre esigenze setup.py da importare NumPy, che causerà un errore se si tenta di pip install vostro progetto senza correre pip install numpy prima.

Se il tuo progetto dipende NumPy, e si desidera NumPy per essere installato automaticamente come dipendenza, è necessario include_dirs impostato solo quando le estensioni sono in realtà in fase di costruzione. È possibile effettuare questa operazione build_ext sottoclasse:

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
)

E si può usare un trucco simile per aggiungere Cython come dipendenza installati automaticamente:

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
)

Nota: questi approcci funzionano solo con pip install .. Essi non lavoro per python setup.py install o python setup.py develop come in questi comandi causano dipendenze da installare dopo il progetto, piuttosto che prima.

Per tutti coloro che non utilizzano Cython, una leggera modifica della soluzione di R_Beagrie senza che la dipendenza è se si build_ext semplicemente importare da distutils.command.build_ext invece di 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
)
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top