72


32

PYTHONPATH vs. sys.path

別の開発者と私は、PYTHONPATHまたはsys.pathを使用して、Pythonがユーザー(開発など)ディレクトリでPythonパッケージを検索できるようにするかどうかに同意しません。

典型的なディレクトリ構造を持つPythonプロジェクトがあります:

Project
    setup.py
    package
        __init__.py
        lib.py
        script.py

script.pyでは、 `import package.lib`を実行する必要があります。 パッケージがサイトパッケージにインストールされると、script.pyは `package.lib`を見つけることができます。

ただし、ユーザーディレクトリから作業する場合は、他に何かを行う必要があります。 私の解決策は、PYTHONPATHに「〜/ Project」が含まれるように設定することです。 別の開発者は、script.pyの先頭に次のコード行を追加したいと考えています。

sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

Pythonが `package.lib`のローカルコピーを見つけることができるように。

この行は開発者またはローカルコピーから実行するユーザーにのみ役立つため、これは悪い考えだと思いますが、それが悪い考えである理由を説明することはできません。

PYTOHNPATH、sys.pathを使用する必要がありますか、それとも問題ありませんか?

5 Answer


41


パスを変更する唯一の理由が作業ツリーから作業している開発者向けである場合、インストールツールを使用して環境をセットアップする必要があります。 virtualenvは非常に人気があり、setuptoolsを使用している場合は、単に `setup.py developer`を実行して、現在のPythonインストールに作業ツリーを半インストールできます。


34


私はPYTHONPATHが嫌いです。 ユーザーごとに設定して(特にデーモンユーザーの場合)設定し、プロジェクトフォルダーが移動するのを追跡するのはもろくて面倒です。 むしろ、スタンドアロンプ​​ロジェクトの呼び出しスクリプトで `sys.path`を設定したいです。

しかし、 sys.path.append`はそれを行う方法ではありません。 簡単に重複を取得でき、 `.pth`ファイルを整理しません。 より良い(そしてより読みやすい): `site.addsitedir

そして、 script.py`はそれを行うのにふさわしい場所ではありません。パスで利用可能にしたいパッケージの内部にあるからです。 ライブラリモジュールは確かに「sys.path」自体に触れてはいけません。 代わりに、通常、アプリのインスタンス化と実行に使用するパッケージの外にhashbanged-scriptがあり、この簡単なラッパースクリプトに、 `sys.path-frobbingのような展開の詳細を入れます。


8


一般に、環境変数(PYTHONPATHなど)の設定は悪い習慣であると考えます。 これは1回限りのデバッグには適していますが、これを通常の方法として使用することはお勧めできません。

環境変数を使用すると、コードベースで問題が報告されたときに「それが機能する」などの状況が発生します。 また、テスト環境でも同じプラクティスを実行し、特定の開発者にとってテストは正常に実行されるが、テストを起動したときに失敗するような状況につながる可能性があります。


4


この場合、PYTHONPATHを使用する方が良いと思います。これは主に(疑わしい)不必要なコードを導入しないためです。

結局のところ、パッケージシステムを使用するため、パッケージがサイトパッケージにインストールされるため、_user_はその `sys.path`を必要としません。

ユーザーが「ローカルコピー」から呼び出すことを選択した場合、サイトパッケージの外部で使用する場合は、通常、PYTHONPATHにパッケージを手動で追加する必要があると述べています。 。


4


すでに述べた他の多くの理由に加えて、ハードコーディングも指摘できます。

sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath( file ))))

script.pyの場所を推定するため、脆弱です-script.pyがProject / packageにある場合にのみ機能します。 ユーザーがscript.pyを(ほぼ)他の場所に移動/コピー/シンボリックリンクすることを決めた場合、それは壊れます。