あらゆる種類の例やその他の同様の質問を見てきましたが、私のシナリオに完全に一致する例を見つけることができないようです。似たような質問が非常に多いので、これを尋ねるのは本当に愚かなことのように感じますが、これを「正しく」動作させることができないようです。これが私のプロジェクトです。
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スクリプトを使用して1つのディレクトリを上下に参照することはできません。
以下を使用して問題を解決できることに注意してください。
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
import Modules.LDAPManager as LDAPManager
これは悪い習慣であり、落胆すると聞いています。
スクリプトのファイルは直接実行されることを意図しています(スクリプトのinit。pyは必要ですか?)。この場合、-mフラグを指定してCreateUser.pyを実行する必要があることを読みました。これについていくつかのバリエーションを試しましたが、CreateUser.pyにLDAPManager.pyを認識させることができないようです。
CreateUser.py
をメインのuser_managementディレクトリに移動すると、import Modules.LDAPManager
をインポートしてLDAPManager.py
を簡単に使用できます。これは機能します。
しないでください。このようにして、LDAPManager
によって使用されるCreateUser
モジュールは、notは他のインポートを介してインポートされたモジュールと同じになります。これは、モジュール内にグローバルな状態がある場合、またはpickle/unpickling中に問題を引き起こす可能性があります。 Avoidインポートは、モジュールが同じディレクトリにあるためにのみ機能します。
パッケージ構造がある場合、次のいずれかを行う必要があります。
相対インポートを使用します。つまり、CreateUser.py
がScripts/
にある場合:
from ..Modules import LDAPManager
これはwas(past時制に注意してください) PEP 8 = pythonの古いバージョンはそれらをあまりよくサポートしていなかったからですが、この問題は数年前に解決されました。 currentバージョンのPEP 8doesは、それらを絶対インポートの代替として受け入れられることを示唆しています。私は実際にパッケージ内でlikeしています。
パッケージ名全体を使用して絶対インポートを使用します(CreateUser.py
in Scripts/
):
from user_management.Modules import LDAPManager
2番目のパッケージが機能するには、user_management
をPYTHONPATH
内にインストールする必要があります。開発中にIDEを設定して、手動でsys.path.append
への呼び出しを追加することなく、これを実現できます。
また、Scripts/
がサブパッケージであることは奇妙に感じます。実際のインストールでは、user_management
モジュールはsite-packages
ディレクトリ(OSにライブラリをインストールするために使用されるディレクトリ)にあるlib/
の下にインストールされるため、スクリプトをインストールする必要があるためbin/
ディレクトリの下(OSの実行可能ファイルが含まれている方)。
実際、Script/
はuser_management
の下にあるべきではないと考えています。 user_management
と同じレベルである必要があります。この方法では、not-m
を使用する必要がありますが、単にパッケージが見つかることを確認する必要があります(これもIDEの構成の問題です。パッケージを正しくインストールするか、PYTHONPATH=. python Scripts/CreateUser.py
を使用して正しいパスでスクリプトを起動します)。
要約すると、使用する階層Iは次のとおりです。
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
親ディレクトリをPYTHONPATH
に追加してScripts/
を起動します(両方の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
alwaysはtoplevelモジュールX
をインポートすることを意味し、インポートを試みません同じディレクトリにあるX.py
ファイル(そのディレクトリがPYTHONPATH
にない場合)。このように、相対インポートを行うonly方法は、explicit構文(from . import X
)を使用することです。これは優れています(explicitはimplicitよりも優れています)。
これにより、「間違った」暗黙的な相対インポートを使用しないようにすることができます。これは、何かが間違っていることを明確に示すImportError
を生成するためです。それ以外の場合は、自分が思っているものとは異なるモジュールを使用できます。
Python 2.5以降では、次を使用できます。
from ..Modules import LDAPManager
先行期間では、階層のレベルを「上げる」ことができます。
インポートについては、 パッケージ内参照 のPythonドキュメントを参照してください。
「ルート」__init__.py
では、次のこともできます。
import sys
sys.path.insert(1, '.')
これにより、両方のモジュールがインポート可能になります。