2016-09-30 10 views
1

次のような状況が不思議です。 project_alphaproject_bravoの2つのプロジェクトがあり、いずれもトップレベルの名前空間パッケージmymetaを定義しているとしましょう。レイアウト:同じ名前空間内のパッケージ:セットアップスクリプトのモジュールをインポートできません

project_alpha/ 
    -> mymeta/ 
     -> __init__.py 
     -> project_alpha/ 
      -> __init__.py 
      -> version.py 
    -> setup.py 

project_bravo/ 
    -> mymeta/ 
     -> __init__.py 
     -> project_bravo/ 
      -> __init__.py 
      -> version.py 
    -> setup.py 

両方mymeta/__init__.py sは(namespace section in setuptools docsに従って)のみライン__import__('pkg_resources').declare_namespace(__name__)を含みます。両方version.py Sの内容:

__version_info__ = (0, 9, 9, 'dev0') 
__version__ = '.'.join((str(entry) for entry in __version_info__)) 

project_alphaためsetup.pyスクリプトは非常に単純です。名前空間のパッケージmymetaが宣言され、バージョンがversionモジュールから取得されます:

# project_alpha 
from setuptools import find_packages, setup 
from mymeta.project_alpha.version import __version__ 

setup(
    name='mymeta.project-alpha', 
    version=__version__, 
    namespace_packages=['mymeta'], 
    packages=find_packages(), 
) 

project_bravoためsetup.pyスクリプトはなく、ひねりを加えた、同一の構造を有する:構築するときproject_bravoproject_alphaによって異なります

from setuptools import find_packages, setup 
from mymeta.project_bravo.version import __version__ 

setup(
    name='mymeta.project-bravo', 
    version=__version__, 
    namespace_packages=['mymeta'], 
    setup_requires=['mymeta.project-alpha'], 
    packages=find_packages(), 
) 

project_bravoを構築するとき、私は次のエラーを取得する:

~/project_bravo $ python setup.py sdist 
Traceback (most recent call last): 
    File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/sandbox.py", line 156, in save_modules 
    yield saved 
    File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/sandbox.py", line 197, in setup_context 
    yield 
    File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/sandbox.py", line 246, in run_setup 
    DirectorySandbox(setup_dir).run(runner) 
    File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/sandbox.py", line 276, in run 
    return func() 
    File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/sandbox.py", line 245, in runner 
    _execfile(setup_script, ns) 
    File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/sandbox.py", line 47, in _execfile 
    exec(code, globals, locals) 
    File "/tmp/easy_install-ahmxos98/mymeta.project-alpha-0.9.9.dev0/setup.py", line 6, in <module> 
    try: 
ImportError: No module named 'mymeta.project_alpha' 

During handling of the above exception, another exception occurred: 

Traceback (most recent call last): 
    File "setup.py", line 22, in <module> 
    packages=find_packages(), 
    File "/usr/lib64/python3.5/distutils/core.py", line 108, in setup 
    _setup_distribution = dist = klass(attrs) 
    File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/dist.py", line 315, in __init__ 
    self.fetch_build_eggs(attrs['setup_requires']) 
    File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/dist.py", line 361, in fetch_build_eggs 
    replace_conflicting=True, 
    File "/tmp/tstenv/lib/python3.5/site-packages/pkg_resources/__init__.py", line 853, in resolve 
    dist = best[req.key] = env.best_match(req, ws, installer) 
    File "/tmp/tstenv/lib/python3.5/site-packages/pkg_resources/__init__.py", line 1125, in best_match 
    return self.obtain(req, installer) 
    File "/tmp/tstenv/lib/python3.5/site-packages/pkg_resources/__init__.py", line 1137, in obtain 
    return installer(requirement) 
    File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/dist.py", line 429, in fetch_build_egg 
    return cmd.easy_install(req) 
    File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/command/easy_install.py", line 665, in easy_install 
    return self.install_item(spec, dist.location, tmpdir, deps) 
    File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/command/easy_install.py", line 695, in install_item 
    dists = self.install_eggs(spec, download, tmpdir) 
    File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/command/easy_install.py", line 876, in install_eggs 
    return self.build_and_install(setup_script, setup_base) 
    File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/command/easy_install.py", line 1115, in build_and_install 
    self.run_setup(setup_script, setup_base, args) 
    File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/command/easy_install.py", line 1101, in run_setup 
    run_setup(setup_script, args) 
    File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/sandbox.py", line 249, in run_setup 
    raise 
    File "/usr/lib64/python3.5/contextlib.py", line 77, in __exit__ 
    self.gen.throw(type, value, traceback) 
    File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/sandbox.py", line 197, in setup_context 
    yield 
    File "/usr/lib64/python3.5/contextlib.py", line 77, in __exit__ 
    self.gen.throw(type, value, traceback) 
    File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/sandbox.py", line 168, in save_modules 
    saved_exc.resume() 
    File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/sandbox.py", line 143, in resume 
    six.reraise(type, exc, self._tb) 
    File "/tmp/tstenv/lib/python3.5/site-packages/pkg_resources/_vendor/six.py", line 685, in reraise 
    raise value.with_traceback(tb) 
    File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/sandbox.py", line 156, in save_modules 
    yield saved 
    File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/sandbox.py", line 197, in setup_context 
    yield 
    File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/sandbox.py", line 246, in run_setup 
    DirectorySandbox(setup_dir).run(runner) 
    File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/sandbox.py", line 276, in run 
    return func() 
    File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/sandbox.py", line 245, in runner 
    _execfile(setup_script, ns) 
    File "/tmp/tstenv/lib/python3.5/site-packages/setuptools/sandbox.py", line 47, in _execfile 
    exec(code, globals, locals) 
    File "/tmp/easy_install-ahmxos98/mymeta.project-alpha-0.9.9.dev0/setup.py", line 6, in <module> 
    try: 
ImportError: No module named 'mymeta.project_alpha' 

残念ながら、私はここでのエラーを理解していません。それは輸入秩序と関係していますよね?私はproject_bravo/setup.pymymeta.project_bravo.versionの輸入をコメントアウトし、いくつかのハードコーディングされた文字列でversionを交換した場合、突然、ビルドは...


編集を成功:私は、この問題の回避策を導入しました。バージョンを直接インポートするのではなく、インポートの問題を回避するためにバージョンモジュールI execを使用します。もちろん、これは、このように答えとしてこれを投稿していない、適切な解決策はないが、それでもここではありません:

__version__ = None # if the exec fails, leave the version unset, the resulting build version will be 0.0.0 
version_script_path = os.path.relpath(os.path.join(os.path.dirname(__file__), 'mymeta', 'project_alpha', 'version.py')) 
with open(version_script_path) as version_script: 
    exec(version_script.read()) 

バージョンのスクリプトが読み込まれて実行された後、バージョンが初期化され、インポートするため必要何でもmymetaパッケージから。

+0

エラーを再現しようとしましたが、できませんでした。私のシステムでは、すべて正常に動作します。多分、新鮮なvirtualenvで試してみてください。 'mymeta.project_bravo'をビルドしようとする前に' mymeta.project_alpha'をどのように提供しますか? 'mymeta.project_alpha'に' setup.py install'をしますか? – roman

+0

ああ、私はそれを言い忘れました。 'project_alpha'をプライベートPyPIリポジトリにアップロードする' python setup.py sdist upload'を発行します。 – hoefling

+0

うん、 'python setup.py install'も私のために働いていますが、これは' project_alpha'をvenvに明示的にインストールするので、パッケージは 'project_bravo'をビルドするときに既に存在しています。この問題は 'setuptools'が 'project_alpha'のeggを' project_bravo/.eggs'ディレクトリにダウンロードしようとしたときにのみ表示されます。 – hoefling

答えて

1

約1年後、もう一度この問題に直面しました。python>=3.3の解決策は、PEP 420で指定された暗黙的な名前空間パッケージを使用することです。プロジェクト構造がかろうじてちょうどpkgutilスタイルの名前空間のパッケージmymetaため__init__.py sの両方がなくなっている、変更された:

project_alpha/ 
    -> mymeta/ 
     -> project_alpha/ 
      -> __init__.py 
      -> version.py 
    -> setup.py 

project_bravo/ 
    -> mymeta/ 
     -> project_bravo/ 
      -> __init__.py 
      -> version.py 
    -> setup.py 

setuptoolsを幸せにするために、両方のセットアップ・スクリプトは、同様に調整する必要があります。

... 
setup(
    ... 
    packages=['mymeta.' + pkg for pkg in find_packages('mymeta')], 
) 

project-bravoをビルドするときにインポートが正しく解決されるようになりました。

1

コメントで述べたように:コマンドmymeta.project_bravoため

$ python setup.py sdist 

は、プライベートは、PyPIのレポからmymeta.project_alphaの卵をダウンロードします。

名前空間パッケージは、インポートに関して非常に繊細です。

私は、ns.ans.bを私の環境に定期的にインストールし、0123のディレクトリにある.pthファイルにns.dのインポートパスを指定すると、それは動作しません。しかし、site-packeges/nsディレクトリのns.dにシンボリックリンクすると動作します。

すべてのコンポーネントをインストールせずに、site-packagesディレクトリに.pthのすべてのパスを指定すると、すべて正常に動作します。

すべてのコンポーネントを定期的にインストールしても、すべて正常に動作します。

私はコンセプトを混ぜると動作しません。

したがって、私はこれもここで問題になると思われます。インポートパスのさまざまな戦略。

あなたはあなたに__init__.pyファイルを変更しようとする場合があります:私は名前空間のパッケージを行うには、私の決断を後悔

from pkgutil import extend_path 

__path__ = extend_path(__path__, __name__) 
__import__('pkg_resources').declare_namespace(__name__) 

。私はもう一度やりません。

+0

残念ながら、これは役に立ちません。それにもかかわらず、答えがエラーの原因を説明してくれてありがとう、あなたの努力に感謝します。 – hoefling

+0

こんにちは、まだ解決策に興味があるなら、Python 3.3以上のものを見つけました。暗黙の名前空間パッケージです。詳細は私の答えを見てください。 – hoefling

関連する問題