Python:プロジェクト階層の同じレベルにある別のディレクトリからモジュールをインポートします


87

いろいろな例や他の同様の質問を見てきましたが、私のシナリオに完全に一致する例を見つけることができないようです。似たような質問がたくさんあるので、これを聞いているような気がしますが、これを「正しく」機能させることができないようです。これが私のプロジェクトです:

user_management  (package)
        |
        |------- __init__.py
        |
        |------- Modules/
        |           |
        |           |----- __init__.py
        |           |----- LDAPManager.py
        |           |----- PasswordManager.py
        |
        |------- Scripts/
        |           |
        |           |----- __init__.py
        |           |----- CreateUser.py
        |           |----- FindUser.py

「CreateUser.py」をメインのuser_managementディレクトリに移動すると、次のように簡単に使用できます"import Modules.LDAPManager"。LDAPManager.pyをインポートする---これは機能します。私ができないこと(やりたいこと)は、CreateUser.pyをScriptsサブフォルダーに保持し、LDAPManager.pyをインポートすることです。私はを使用してこれを達成したいと思っていました"import user_management.Modules.LDAPManager.py"。これは機能しません。要するに、Pythonファイルを階層内で簡単に深く見ることができますが、あるディレクトリを上に、別のディレクトリに下に参照するPythonスクリプトを取得することはできません。

以下を使用して問題を解決できることに注意してください。

sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
import Modules.LDAPManager as LDAPManager

これは悪い習慣であり、落胆していると聞きました。

スクリプト内のファイルは直接実行することを目的としています(スクリプト内のinit .pyは必要ですか?)。この場合、-mフラグを指定してCreateUser.pyを実行する必要があることを読みました。これについていくつかのバリエーションを試しましたが、CreateUser.pyにLDAPManager.pyを認識させることができないようです。

回答:


66

CreateUser.pyメインのuser_managementディレクトリに移動すると、次のコマンドを簡単に使用できます 。import Modules.LDAPManagerインポートLDAPManager.py---これは機能します。

しないでください。このように、LDAPManagerによって使用さCreateUserれるモジュールは、他のインポートを介してインポートされたモジュールと同じにはなりません。これにより、モジュール内にグローバル状態がある場合、またはピクルス/ピクルス解除中に問題が発生する可能性があります。モジュールがたまたま同じディレクトリにあるという理由だけで機能するインポートは避けてください

パッケージ構造がある場合は、次のいずれかを行う必要があります。

  • 相対インポートを使用します。つまり、CreateUser.pyが次の場合Scripts/

     from ..Modules import LDAPManager
    

    これ過去形に注意してください)PEP 8によって推奨されなかったことに注意してください。これ、古いバージョンのpythonがそれらを十分にサポートしていなかったためですが、この問題は数年前に解決されました。現在PEP 8のバージョンではない絶対的な輸入品に許容可能な代替として、それらを示唆しています。私は実際にパッケージ内でそれらが好きです。

  • パッケージ名全体CreateUser.pyScripts/使用して絶対インポートを使用します

     from user_management.Modules import LDAPManager
    

2つ目が機能するためには、パッケージuser_managementをの中にインストールする必要がありPYTHONPATHます。開発中に、sys.path.appendどこにでも手動で呼び出しを追加しなくても、これが発生するようにIDEを構成できます。

また、それScripts/がサブパッケージであるのは奇妙だと思います。実際のインストールであるためuser_management、モジュールが下にインストールされますsite-packagesで見つかったlib/スクリプトが下にインストールする必要がある一方で、(あなたのOSでライブラリをインストールするために使用された方のディレクトリ)のディレクトリbin/のディレクトリ(あなたのOS用の実行可能ファイルが含まれている方)。

実際、私はScript/下にあるべきではないと信じていますuser_management。と同じレベルである必要がありuser_managementます。このように、を使用する必要はありません-m、パッケージが見つかることを確認するだけです(これも、IDEの構成、パッケージの正しいインストール、またはPYTHONPATH=. python Scripts/CreateUser.py正しいパスでスクリプトを起動するために使用する問題です)。


要約すると、が使用する階層は次のとおりです。

user_management  (package)
        |
        |------- __init__.py
        |
        |------- Modules/
        |           |
        |           |----- __init__.py
        |           |----- LDAPManager.py
        |           |----- PasswordManager.py
        |

 Scripts/  (*not* a package)
        |  
        |----- CreateUser.py
        |----- FindUser.py

その後のコードCreateUser.pyとは、FindUser.pyモジュールをインポートするために、絶対的なインポートを使用する必要があります。

from user_management.Modules import LDAPManager

インストール中に、モジュールを見つけられるように、実行可能ファイルのディレクトリ内のスクリプトがのuser_managementどこかにあるPYTHONPATHことを確認します。開発中にどちらかのIDEの設定に依存している、またはあなたが起動するCreateUser.py追加Scripts/の親ディレクトリをPYTHONPATH(私は両方入っているディレクトリを意味するuser_managementとのScripts):

PYTHONPATH=/the/parent/directory python Scripts/CreateUser.py

またはPYTHONPATH、毎回これを指定する必要がないように、グローバルに変更することもできます。UNIX OS(Linux、Mac OS Xなど)では、シェルスクリプトの1つを変更してPYTHONPATH外部変数を定義できます。Windowsでは、環境変数の設定を変更する必要があります。


補遺python2を使用している場合は、次のように入力して、暗黙的な相対インポートを回避することをお勧めします。

from __future__ import absolute_import

モジュールの上部にあります。このように、import X 常に上位モジュールをインポートすることを意味し、同じディレクトリにXあるX.pyファイルをインポートしようとはしません(そのディレクトリがにない場合PYTHONPATH)。このように、相対インポートを行う唯一の方法は、明示的な構文(from . import X)を使用することです。これは、より優れています(明示的は暗黙的よりも優れています)。

これにより、「偽の」暗黙的な相対インポートを使用することがないようになります。これはImportError、何かが間違っていることを明確に示す信号を生成するためです。そうでなければ、あなたはそれが思っているものではないモジュールを使うことができます。


相対インポートを使用している場合は、実行する必要がありますpython -m user_management.Scripts.CreateUser
mononoke 2017年

14

Python 2.5以降、次を使用できます

from ..Modules import LDAPManager

主要な期間は、階層のレベルを「上げる」ことになります。

インポートのパッケージ内参照に関するPythonドキュメントを参照してください。


3

「ルート」では、__init__.py次のこともできます。

import sys
sys.path.insert(1, '.')

これにより、両方のモジュールがインポート可能になります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.