web-dev-qa-db-ja.com

Cythonでsetup_requires?

Cython拡張モジュールをいくつか含むプロジェクトのsetup.pyファイルを作成しています。

私はすでにこれを機能させています:

from setuptools import setup, Extension
from Cython.Build import cythonize

setup(
    name=...,
    ...,
    ext_modules=cythonize([ ... ]),
)

これは正常にインストールされます。ただし、これはCythonがインストールされていることを前提としています。インストールされていない場合はどうなりますか?これがsetup_requiresパラメータの目的であることを理解しています。

from setuptools import setup, Extension
from Cython.Build import cythonize

setup(
    name=...,
    ...,
    setup_requires=['Cython'],
    ...,
    ext_modules=cythonize([ ... ]),
)

ただし、Cythonがまだインストールされていない場合、これはもちろん失敗します。

$ python setup.py install
Traceback (most recent call last):
  File "setup.py", line 2, in <module>
    from Cython.Build import cythonize
ImportError: No module named Cython.Build

これを行う適切な方法は何ですか? setup_requiresステップの実行後にのみ、何らかの方法でCythonをインポートする必要がありますが、ext_modulesの値を指定するには、Cythonが必要です。

24
Claudiu

from Cython.Build import cythonizetry-exceptでラップし、exceptcythonizeをダミー関数として定義する必要があります。これにより、ImportErrorで失敗することなくスクリプトをロードできます。

その後、setup_requires引数が処理されると、Cythonがインストールされ、セットアップスクリプトが再実行されます。その時点でCythonがインストールされているので、cythonizeを正常にインポートできます

try:
    from Cython.Build import cythonize
except ImportError:
     def cythonize(*args, **kwargs):
         from Cython.Build import cythonize
         return cythonize(*args, **kwargs)

編集

コメントに記載されているように、欠落した依存関係をsetuptoolsが処理した後は、Cythonを再ロードしません。私はこれまで考えたことはありませんでしたが、cythonizeをスタブ化するために遅延バインディングのアプローチを試すこともできます。

4
mobiusklein