Python検索パスを他のソースに拡張する


106

かなり大規模な既存のコードベースでプロジェクトに参加しました。Linuxで開発しており、IDEは使用していません。コマンドラインを実行します。プロジェクトモジュールを実行するときにpythonに正しいパスを検索させる方法を理解しようとしています。たとえば、私が次のようなものを実行すると:

python someprojectfile.py

私は得る

ImportError: no module named core.'somemodule'

すべてのインポートでこれが表示されますが、パスの問題だと思います。

TLDR:

~/codez/project/インポートステートメント中にPython で* .pyファイルのすべてのファイルとフォルダーを検索するにはどうすればよいですか。

回答:


171

これにはいくつかの方法があります。

  • 環境変数PYTHONPATHをコロンで区切られたディレクトリのリストに設定して、インポートされたモジュールを検索します。
  • プログラムで、を使用sys.path.append('/path/to/search')して、インポートしたモジュールをPythonで検索するディレクトリの名前を追加します。sys.pathPythonがモジュールのインポートを要求されるたびに検索するディレクトリのリストであり、必要に応じて変更できます(ただし、標準のディレクトリを削除することはお勧めしません!)。環境変数に配置したディレクトリは、Pythonの起動時PYTHONPATHに挿入さsys.pathれます。
  • site.addsitedirディレクトリを追加するために使用しsys.pathます。これと単純な追加の違いは、を使用するとaddsitedir.pthそのディレクトリ内のファイルも検索し、ファイルsys.pathの内容に基づいてに追加のディレクトリを追加するためにそれらを使用することです。詳細については、ドキュメントを参照してください。

どちらを使用するかは、状況によって異なります。プロジェクトを他のユーザーに配布する場合、他のユーザーは通常、PythonコードファイルがPythonのインポーターによって自動的に検出されるように(つまり、パッケージは通常site-packagesディレクトリにインストールされます)インストールするためsys.path、コードをいじる場合、それは不必要な場合があり、そのコードが別のコンピューターで実行されると悪影響を与える可能性もあります。開発についてPYTHONPATHは、通常、設定が最善の方法だと思います。

ただし、自分のコンピューターで実行するだけのものを使用している場合(またはWebアプリケーションのフレームワークなど、標準以外の設定を使用している場合)は、次のようなことを行うことも珍しくありません。

import sys
from os.path import dirname
sys.path.append(dirname(__file__))

それで、たとえば15個のサブディレクトリがあるとしたら、それぞれを個別に追加する必要がありますか?
themaestro

そして、PYTHONPATHを変更するためのコマンドライン引数の例を挙げてもらえますか?
themaestro

3
セットへPYTHONPATH:で.bashrc書き込み、または何でも(それはバッシュはない場合)あなたのシェルの使用を提出STARTUP export PYTHONPATH=$PYTHONPATH:$HOME/codez/project。しかし、サブディレクトリがたくさんある場合は、.pthファイルを作成してを使用しますsite.addsitedirsitecustomize関数を呼び出すことができるモジュールを作成できます。~/.local/lib/python2.6/sitecustomize.py(Pythonバージョンを置き換えて)に置いてみてください。うまくいけば、自動的にインポートされます。
David Z

以下を.bashrcファイルに入れても、それらのインポートにはまだ運がありません。何か案は?とにかく、.pthファイルをどのように作成しますか?export PYTHONPATH = $ PYTHONPATH:$ HOME / adaifotis / codez / export PYTHONPATH = $ PYTHONPATH:$ HOME / adaifotis / codez / project export PYTHONPATH = $ PYTHONPATH:$ HOME / adaifotis / codez / project / core export PYTHONPATH = $ PYTHONPATH:$ HOME / adaifotis / codez / project / proxies export PYTHONPATH = $ PYTHONPATH:$ HOME / adaifotis / codez / project / conf
themaestro

端末を開いて実行してみてくださいecho $PYTHONPATH。環境変数が正しく設定されている場合は、コロンで区切られたディレクトリのリストが表示されます。詳細については.pth、ファイル、のドキュメントを参照site、私は私の答えににリンクされているモジュールを。内容と使用方法がわかります。
David Z

13

こちらのpythonパッケージについてもお読みください:http : //docs.python.org/tutorial/modules.html

あなたの例から、私はあなたが本当にパッケージを持っていると思います~/codez/project__init__.pypythonディレクトリ内のファイルは、ディレクトリをネームスペースにマップします。すべてのサブディレクトリに__init__.pyファイルがある場合は、ベースディレクトリをに追加するだけで済みますPYTHONPATH。例えば:

PYTHONPATH = $ PYTHONPATH:$ HOME / adaifotis / project

Davidが説明するように、PYTHONPATH環境変数のテストに加えて、次のようにpythonでテストできます。

$ python
>>> import project                      # should work if PYTHONPATH set
>>> import sys
>>> for line in sys.path: print line    # print current python path

...


__init__.py逆に__init__.pyではなく、本当に意味していることを明確にするためにバッククォートを入れたいと思うかもしれませんinit.py。初心者を混乱させないために。:)
2015

4

このスレッドは少し古いことは知っていますが、ここまでたどり着くまでに少し時間がかかったので、共有したいと思います。

私のプロジェクトでは、メインスクリプトを親ディレクトリに配置し、モジュールを区別するために、すべてのサポートモジュールを「モジュール」と呼ばれるサブフォルダーに配置しました。私のメインスクリプトでは、次のようにこれらのモジュールをインポートします(report.pyというモジュールの場合)。

from modules.report import report, reportError

メインスクリプトを呼び出すと、これは機能します。ただし、次のようにmain()、それぞれにa を含め、それぞれを直接呼び出すことで、各モジュールをテストしたいと思いました。

python modules/report.py

Pythonは「モジュールと呼ばれるモジュール」が見つからないと不平を言います。ここで重要なのは、デフォルトでは、Pythonは検索パスにスクリプトのフォルダーを含めますが、CWDは含めないということです。つまり、このエラーが実際に言っているのは、「モジュールのサブフォルダーが見つからない」ということです。これは、report.pyモジュールが存在するディレクトリからの「モジュール」サブディレクトリがないためです。

これに対する最も近い解決策は、これを先頭に含めることにより、CWDをPython検索パスに追加することです。

import sys

sys.path.append(".")

PythonはCWD(現在のディレクトリ)を検索し、「modules」サブフォルダーを見つけます。すべて順調です。


3

私は答えを探すためにこの質問を読みましたが、どれも好きではありませんでした。

だから私は迅速かつ汚い解決策を書きました。これをsys.pathのどこかに置くだけで、folder(現在の作業ディレクトリから)またはその下に任意のディレクトリが追加されますabspath

#using.py

import sys, os.path

def all_from(folder='', abspath=None):
    """add all dirs under `folder` to sys.path if any .py files are found.
    Use an abspath if you'd rather do it that way.

    Uses the current working directory as the location of using.py. 
    Keep in mind that os.walk goes *all the way* down the directory tree.
    With that, try not to use this on something too close to '/'

    """
    add = set(sys.path)
    if abspath is None:
        cwd = os.path.abspath(os.path.curdir)
        abspath = os.path.join(cwd, folder)
    for root, dirs, files in os.walk(abspath):
        for f in files:
            if f[-3:] in '.py':
                add.add(root)
                break
    for i in add: sys.path.append(i)

>>> import using, sys, pprint
>>> using.all_from('py') #if in ~, /home/user/py/
>>> pprint.pprint(sys.path)
[
#that was easy
]

そして、いくつかのランダムツール用のフォルダーを作成でき、それらをパッケージなどに含めなくても、数行のコードでそれらの一部(またはすべて)にアクセスできるので、気に入っています。


3

私が見つける最も簡単な方法は、ファイル「any_name.pth」を作成し、それをフォルダー「\ Lib \ site-packages」に置くことです。pythonがインストールされている場所ならどこでも、そのフォルダーが見つかるはずです。

そのファイルに、インポートするモジュールを保持するディレクトリのリストを入れます。たとえば、そのファイルに次のような行を作成します。

C:\ Users \ example ... \ example

あなたはそれをPythonで実行することでそれが機能することを伝えることができます:

import sys
for line in sys: print line

インポートできるディレクトリなど、ディレクトリが表示されます。これで、次のように簡単に、そのディレクトリにある「mymodule.py」ファイルをインポートできます。

import mymodule

これはサブフォルダーをインポートしません。そのためには、Pythonスクリプトを作成して、定義したフォルダーのすべてのサブフォルダーを含む.pthファイルを作成することを想像できます。おそらく起動時に実行してください。


0

古い質問の新しいオプション。
インストールfail2banDebianの上でパッケージを、それのようなルックスは上でインストールするためにハードコードされます/usr/lib/python3/dist-packages/fail2banパスではないのpython3にsys.path


> python3
Python 3.7.3 (v3.7.3:ef4ec6ed12, Jun 25 2019, 18:51:50)
[GCC 6.3.0 20170516] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.path
['', '/usr/lib/python37.zip', '/usr/lib/python3.7', '/usr/lib/python3.7/lib-dynload', '/usr/lib/python3.7/site-packages']
>>>

そのため、単にコピーするのではなく、ライブラリを新しいバージョンにリンク(bash)しました。
元のアプリへの将来の更新は、リンクされたバージョンにも自動的に適用されます。

 if [ -d /usr/lib/python3/dist-packages/fail2ban ]
   then
      for d in /usr/lib/python3.*
      do
         [ -d ${d}/fail2ban ] || \
            ln -vs /usr/lib/python3/dist-packages/fail2ban ${d}/
      done
   fi
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.