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
が必要です。
from Cython.Build import cythonize
をtry-except
でラップし、except
でcythonize
をダミー関数として定義する必要があります。これにより、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
をスタブ化するために遅延バインディングのアプローチを試すこともできます。