Numpyを必要とするC拡張機能を持つプロジェクトがあります。理想的には、プロジェクトをダウンロードする人は誰でも_python setup.py install
_を実行できるようにするか、pip
を1回呼び出すだけでよいようにします。私が抱えている問題は、_setup.py
_でヘッダーの場所を取得するためにnumpyをインポートする必要があるということですが、numpyを_install_requires
_の通常の要件にして、自動的にPythonパッケージインデックスからダウンロード。
これが私がやろうとしていることのサンプルです:
_from setuptools import setup, Extension
import numpy as np
ext_modules = [Extension('vme', ['vme.c'], extra_link_args=['-lvme'],
include_dirs=[np.get_include()])]
setup(name='vme',
version='0.1',
description='Module for communicating over VME with CAEN digitizers.',
ext_modules=ext_modules,
install_requires=['numpy','pyzmq', 'Sphinx'])
_
明らかに、インストールする前に上部に_import numpy
_することはできません。 setup()
に渡された_setup_requires
_引数を見ましたが、その目的に関するドキュメントが見つかりません。
これは可能ですか?
以下は、少なくともnumpy1.8とpython {2.6,2.7,3.3}で機能します。
from setuptools import setup
from setuptools.command.build_ext import build_ext as _build_ext
class build_ext(_build_ext):
def finalize_options(self):
_build_ext.finalize_options(self)
# Prevent numpy from thinking it is still in its setup process:
__builtins__.__NUMPY_SETUP__ = False
import numpy
self.include_dirs.append(numpy.get_include())
setup(
...
cmdclass={'build_ext':build_ext},
setup_requires=['numpy'],
...
)
簡単な説明については、「ハック」なしで失敗する理由を参照してください。 この回答 を参照してください。
setup_requires
の使用には微妙な欠点があることに注意してください。たとえば、numpyは拡張機能をビルドする前だけでなく、python setup.py --help
を実行するときにもコンパイルされます。これを回避するには、 https://github.com/scipy/scipy/blob/master/setup.py#L205 で提案されているように、コマンドラインオプションを確認できますが、その一方で、努力する価値があるとは思わないでください。
これは、numpy(distutilsまたはget_includeの場合)を使用する必要があるパッケージの基本的な問題です。 pipまたはeasy-installを使用して「ブートストラップ」する方法がわかりません。
ただし、モジュールのcondaパッケージを作成し、依存関係のリストを提供するのは簡単です。これにより、誰かがconda install pkg-nameを実行するだけで、必要なものすべてをダウンロードしてインストールできます。
CondaはAnacondaまたはMiniconda(python +単なるconda)で利用できます。
詳細については、次のWebサイトを参照してください: http://docs.continuum.io/conda/index.html またはこのスライドデッキ: https://speakerdeck.com/teoliphant/packaging -and-deployment-with-conda
Pipを機能させるには、Scipyと同様に行うことができます: https://github.com/scipy/scipy/blob/master/setup.py#L205
つまり、Egg_info
コマンドを標準のsetuptools/distutilsに渡す必要がありますが、他のコマンドではnumpy.distutils
を使用できます。
おそらく、より実用的な解決策は、事前にnumpyをインストールしてimport numpy
関数スコープ内。 @coldfixソリューションは機能しますが、numpyのコンパイルには永遠に時間がかかります。 manylinux のような努力のおかげで、ほとんどのシステムにホイールが用意されたので、最初にホイールパッケージとしてpipインストールする方がはるかに高速です。
from __future__ import print_function
import sys
import textwrap
import pkg_resources
from setuptools import setup, Extension
def is_installed(requirement):
try:
pkg_resources.require(requirement)
except pkg_resources.ResolutionError:
return False
else:
return True
if not is_installed('numpy>=1.11.0'):
print(textwrap.dedent("""
Error: numpy needs to be installed first. You can install it via:
$ pip install numpy
"""), file=sys.stderr)
exit(1)
def ext_modules():
import numpy as np
some_extention = Extension(..., include_dirs=[np.get_include()])
return [some_extention]
setup(
ext_modules=ext_modules(),
)
@ coldfixのソリューション Cythonでは機能しません-Cythonがターゲットマシンにプリインストールされていない場合、エラーで失敗するため、拡張機能
エラー:不明なファイルタイプ '.pyx'( 'xxxxx/yyyyyy.pyx'から)
失敗の理由は、setuptools.command.build_ext
のインポートが時期尚早であるためです。インポートすると、 使用しようとします Cythonのbuild_ext
-機能:
try:
# Attempt to use Cython for building extensions, if available
from Cython.Distutils.build_ext import build_ext as _build_ext
# Additionally, assert that the compiler module will load
# also. Ref #1229.
__import__('Cython.Compiler.Main')
except ImportError:
_build_ext = _du_build_ext
インポートはsetup_requirements
が実行された後に行われるため、通常はsetuptoolsが成功します。ただし、すでにsetup.py
にインポートすることにより、フォールバックソリューションのみを使用できます。これはCythonについて何も知りません。
bootstrap Cython
とnumpyの1つの可能性は、間接参照/プロキシを使用してsetuptools.command.build_ext
のインポートを延期することです。
# factory function
def my_build_ext(pars):
# import delayed:
from setuptools.command.build_ext import build_ext as _build_ext#
# include_dirs adjusted:
class build_ext(_build_ext):
def finalize_options(self):
_build_ext.finalize_options(self)
# Prevent numpy from thinking it is still in its setup process:
__builtins__.__NUMPY_SETUP__ = False
import numpy
self.include_dirs.append(numpy.get_include())
#object returned:
return build_ext(pars)
...
setup(
...
cmdclass={'build_ext' : my_build_ext},
...
)
他にも可能性があります。たとえば、この SO-question で説明します。
[この投稿] [1]で非常に簡単な解決策を見つけました:
または、 https://github.com/pypa/pip/issues/5761 に固執することもできます。ここでは、実際のセットアップの前に、setuptools.distを使用してcythonとnumpyをインストールします。
from setuptools import dist
dist.Distribution().fetch_build_eggs(['Cython>=0.15.1', 'numpy>=1.10'])
私にとってはうまくいきます!