26

Python での相対インポートの使用には 1 つの欠点があります。例外が発生するため、モジュールをスタンドアロンとして実行できなくなります。ValueError: Attempted relative import in non-package

# /test.py: just a sample file importing foo module
import foo
...

# /foo/foo.py:
from . import bar
...
if __name__ == "__main__":
   pass

# /foo/bar.py: a submodule of foo, used by foo.py
from . import foo
...
if __name__ == "__main__":
   pass

test.pyall:を実行できるようにするfoo.pyには、サンプル コードをどのように変更すればよいですか。bar.py

Python 2.6+ (3.x を含む) で動作するソリューションを探しています。

4

6 に答える 6

22

少し異なる方法で「モジュールをスタンドアロンとして実行する」ことを開始できます。

それ以外の:

python foo/bar.py

使用する:

python -mfoo.bar

もちろん、foo/__init__.pyファイルが存在する必要があります。

foo.pyまた、 と の間に循環依存関係があることに注意してくださいbar.py。これは機能しません。あなたの例ではそれは単なる間違いだと思います。

更新:これを の最初の行として使用することも完全にうまくいくようですfoo/bar.py:

#!/usr/bin/python -mfoo.bar

その後、スクリプトを POSIX システムで直接実行できます。

于 2010-09-01T12:23:36.463 に答える
16

まず、foo は bar をインポートし、その逆も同様であるため、作成した内容が循環インポートの問題につながることを認識していると思います。追加してみてください

from foo import bar

test.py に追加すると、失敗することがわかります。動作させるには、例を変更する必要があります。

したがって、あなたが求めているのは、相対インポートが失敗したときに絶対インポートにフォールバックすることです。実際、メインモジュールとして foo.py または bar.py を実行している場合、他のモジュールは単にルートレベルにあり、それらがシステム上の別のモジュールと名前を共有している場合、どのモジュールが選択されるかによって異なります。 sys.path の順序。通常、現在のディレクトリが最初にあるため、利用可能な場合はローカル モジュールが選択されます。つまり、現在の作業ディレクトリに「os.py」ファイルがある場合は、組み込みのモジュールの代わりにそれが選択されます。

可能な提案は次のとおりです。

foo.py

try:
    from . import bar
except ValueError:
    import bar

if __name__ == "__main__":
    pass

bar.py:

if __name__ == "__main__":
    pass

ちなみに、通常は適切な位置からスクリプトを呼び出す方がはるか優れています。

python -m foo.bar

おそらく最善の方法です。これにより、モジュールがスクリプトとして実行されます

于 2010-09-05T22:44:53.027 に答える
1

__init__.py各フォルダに必要です。

相対インポートは、次の場合にのみ機能します。

python test.py

test.py imports foo.py と foo.py は、test.py 以上のフォルダから何でも相対インポートできます。

あなたはできません:

cd foo
python foo.py
python bar.py

それは決してうまくいきません。

sys.path.append または sys.path.insert ソリューションを試すことができますが、パスを台無しにして、f=open(filename) で問題が発生します。

于 2011-02-12T07:43:41.600 に答える
1

相対インポートはやめてください: とにかく、パッケージの名前空間はグローバルなものと考えるべきです。

これをおいしくする秘訣は、sys.path適切に編集することです。ここに考えるべきいくつかの食べ物があります:

# 1 つ上のディレクトリ
_root_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
sys.path.insert(0, _root_dir) とりあえず
于 2010-09-06T03:00:23.690 に答える
0

「メイン」を別の .py ファイルに入れないのはなぜですか?

于 2010-09-06T02:55:52.340 に答える
-2

これまでのところ、私が見つけた唯一の解決策は、相対インポートをまったく使用しないことでした。

現在の制限により、いつ誰かが Python で相対インポートを使用することになっているのか疑問に思っています。

私が使用したすべての構成ではsys.path、現在のディレクトリが最初の引数として含まれているため、同じことを行うため、import foo代わりに使用してください。from . import foo

于 2010-09-01T12:10:23.827 に答える