web-dev-qa-db-ja.com

方法Bootstrap setup.pyでのnumpyのインストール

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_引数を見ましたが、その目的に関するドキュメントが見つかりません。

これは可能ですか?

32
user545424

以下は、少なくとも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 で提案されているように、コマンドラインオプションを確認できますが、その一方で、努力する価値があるとは思わないでください。

28
coldfix

これは、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

4
Travis Oliphant

Pipを機能させるには、Scipyと同様に行うことができます: https://github.com/scipy/scipy/blob/master/setup.py#L205

つまり、Egg_infoコマンドを標準のsetuptools/distutilsに渡す必要がありますが、他のコマンドではnumpy.distutilsを使用できます。

2
pv.

おそらく、より実用的な解決策は、事前に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(),
)
2
ksindi

@ 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 で説明します。

0
ead

[この投稿] [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'])

私にとってはうまくいきます!

0
floschl