web-dev-qa-db-ja.com

モジュールをロードするときにsys.path.insert(0、path)およびsys.path(append)を使用する効果

私は最近python ImportErrorの問題を抱えていました。ローカルコンピューターで実行しているときにモジュールが見つかりましたが、CIサーバーでは見つかりませんでした。この問題は、スクリプトのsys.path.append(path)sys.path.insert(0, path)と交換することで解決しました。ここで、pathは文字列モジュールの場所です。

これは私のモジュールであり、インストールされたパッケージではないため( 関連する質問 )、なぜパスの順序がこの問題を修正するのですか?

36
Michael Barton

pythonは、sys.pathリストの最初のディレクトリから順番にディレクトリをチェックインするため、探していた.pyファイルが見つかるまで。

理想的には、現在のディレクトリまたはスクリプトのディレクトリは、変更した場合を除き、リストの最初の要素であり常に最初の要素です。 ドキュメント から-

プログラムの起動時に初期化されると、このリストの最初の項目であるpath [0]は、Pythonインタープリターの呼び出しに使用されたスクリプトを含むディレクトリです。スクリプトディレクトリが利用できない場合(たとえば、インタープリターが対話的に呼び出される場合、またはスクリプトが標準入力から読み取られる場合)、path [0]は空の文字列であり、Pythonに現在のモジュールを検索します最初にディレクトリ。 PYTHONPATHの結果としてエントリが挿入される前に、スクリプトディレクトリが挿入されることに注意してください。

したがって、おそらく、現在のディレクトリ(スクリプトの実行元)に、インポート元のモジュールと同じ名前の.pyファイルがありました。

また、ImportErrorsについて注意することは、インポートエラーが言うことを言うことができます-ImportError: No module named main-それはmain.pyが上書きされることを意味しません読み込もうとする問題。この上のいくつかのモジュールは、.pyまたは他のファイルで上書きされました。

例-

私のディレクトリ構造は次のようになります-

 - test
    - shared
         - __init__.py
         - phtest.py
  - testmain.py

testmain.pyから、from shared import phtestを呼び出して、正常に動作します。

testディレクトリ `にshared.pyを導入したとしましょう。例-

 - test
    - shared
         - __init__.py
         - phtest.py
  - testmain.py 
  - shared.py

from shared import phtestからtestmain.pyを実行しようとすると、エラーが発生します-

ImportError: cannot import name 'phtest'

上記のように、問題の原因となっているファイルはshared.pyではなくphtest.pyです。

24
Anand S Kumar

私はPythonの初心者です。Anandの答えは非常に良いが、私には非常に複雑であることがわかりました。

1)insertおよびappendメソッドはsys.pathに固有ではなく、他の言語と同様に、リストまたは配列にアイテムを追加します。
* append(item)は、リストの最後にitemを追加します。
* insert(n, item)は、リストのn番目の位置にitemを挿入します(先頭に0、最初の要素の後に1など)。

2)アナンドが言ったように、pythonはパスの各ディレクトリにあるインポートファイルをパスの順に検索します。
*ファイル名の衝突がない場合、パスの順序は影響しません。
*パスで既に定義されている関数を処理し、appendを使用してパスを追加する場合、関数ではなく定義済みの関数を取得します。

しかし、appendではなくinsertを使用して、Pythonの標準動作をオーバーロードしないようにし、ファイルとメソッドにあいまいでない名前を使用する方が良いと思います。

24
geekobi