distutils la chiamata e per i file di intestazione numpy nel posto giusto
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)?
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
)