私は、かなり大きな既存のコードベースでプロジェクトに参加しました。 Linuxで開発し、IDEは使用しません。コマンドラインを実行します。プロジェクトモジュールを実行するときにpythonを取得して正しいパスを検索する方法を見つけようとしています。たとえば、次のようなものを実行すると:
python someprojectfile.py
私は得る
ImportError: no module named core.'somemodule'
私はすべてのインポートでこれを取得しますが、パスの問題だと思います。
TLDR:
インポートステートメント中にPythonを取得して~/codez/project/
およびすべてのファイルとフォルダーで* .pyファイルを検索するにはどうすればよいですか。
これを行うには、いくつかの可能な方法があります。
PYTHONPATH
をディレクトリのコロン区切りリストに設定して、インポートされたモジュールを検索します。sys.path.append('/path/to/search')
を使用して、インポートしたモジュールを検索するPythonに必要なディレクトリの名前を追加します。 sys.path
は、ディレクトリのリストですPythonは、モジュールのインポートを求められるたびに検索し、必要に応じて変更できます(ただし、標準ディレクトリ!)。環境変数PYTHONPATH
に配置したディレクトリは、Pythonの起動時に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__))
また、次のpythonパッケージについて読む必要があります。 http://docs.python.org/tutorial/modules.html 。
あなたの例から、あなたは本当に~/codez/project
にパッケージがあると思います。 pythonディレクトリの__init__.py
ファイルは、ディレクトリをネームスペースにマップします。すべてのサブディレクトリに__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
...
私はこのスレッドが少し古いことを知っていますが、これの中心に到達するのに時間がかかりましたので、共有したいと思いました。
私のプロジェクトでは、親ディレクトリにメインスクリプトがあり、モジュールを区別するために、すべてのサポートモジュールを「モジュール」と呼ばれるサブフォルダーに入れました。メインスクリプトで、これらのモジュールを次のようにインポートします(report.pyというモジュールの場合)。
from modules.report import report, reportError
メインスクリプトを呼び出すと、これが機能します。ただし、各モジュールにmain()
を含めて、各モジュールをテストし、それぞれを直接呼び出したいと思いました。
python modules/report.py
Pythonは、「モジュールと呼ばれるモジュール」が見つからないと文句を言います。ここで重要なのは、デフォルトで、Pythonは検索パスにスクリプトのフォルダーを含むことですが、CWDではありません。したがって、このエラーが実際に言うのは、「モジュールのサブフォルダーが見つかりません」です。これは、report.pyモジュールが存在するディレクトリに「モジュール」サブディレクトリがないためです。
これに最も近い解決策は、Python検索パスにCWDを追加することで、これを最上部に含めることです。
import sys
sys.path.append(".")
これでPythonがCWD(現在のディレクトリ)を検索し、「モジュール」サブフォルダーを見つけました。すべてうまくいきました。
私が見つける最も簡単な方法は、ファイル「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ファイルを作成することを想像できます。おそらく起動時に実行してください。
私はこの質問を読んで答えを探しましたが、どれも好きではありませんでした。
だから私は迅速で汚い解決策を書いた。これを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
]
そして、私はいくつかのランダムなツール用のフォルダーを持ち、それらをパッケージまたは何かの一部にせずに、数行のコードでそれらの一部(またはすべて)にアクセスできるので、それが好きです。
古い質問の新しいオプション
Debianにfail2ban
パッケージをインストールすると、/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