相対パスを指定して Python モジュールをインポートするにはどうすればよいですか?
たとえば、 とが含まdirFoo
れFoo.py
ている場合、 にインポートするにはどうすればよいですか?dirBar
dirBar
Bar.py
Bar.py
Foo.py
視覚的な表現は次のとおりです。
dirFoo\
Foo.py
dirBar\
Bar.py
Foo
を含めたいと考えてBar
いますが、フォルダ階層を再構築することはできません。
相対パスを指定して Python モジュールをインポートするにはどうすればよいですか?
たとえば、 とが含まdirFoo
れFoo.py
ている場合、 にインポートするにはどうすればよいですか?dirBar
dirBar
Bar.py
Bar.py
Foo.py
視覚的な表現は次のとおりです。
dirFoo\
Foo.py
dirBar\
Bar.py
Foo
を含めたいと考えてBar
いますが、フォルダ階層を再構築することはできません。
両方のディレクトリが実際の Python パッケージである (内部にファイルがある) と仮定すると__init__.py
、スクリプトの場所に相対的なモジュールを含めるための安全な解決策は次のとおりです。
スクリプトに一連のモジュールを含める必要があるため、これを行いたいと思います。私はこれをいくつかの製品の本番環境で使用しており、次のような多くの特別なシナリオで機能します。別のディレクトリから呼び出されたスクリプト、または新しいインタープリターを開く代わりに python execute で実行されたスクリプト。
import os, sys, inspect
# realpath() will make your script run, even if you symlink it :)
cmd_folder = os.path.realpath(os.path.abspath(os.path.split(inspect.getfile( inspect.currentframe() ))[0]))
if cmd_folder not in sys.path:
sys.path.insert(0, cmd_folder)
# Use this if you want to include modules from a subfolder
cmd_subfolder = os.path.realpath(os.path.abspath(os.path.join(os.path.split(inspect.getfile( inspect.currentframe() ))[0],"subfolder")))
if cmd_subfolder not in sys.path:
sys.path.insert(0, cmd_subfolder)
# Info:
# cmd_folder = os.path.dirname(os.path.abspath(__file__)) # DO NOT USE __file__ !!!
# __file__ fails if the script is called in different ways on Windows.
# __file__ fails if someone does os.chdir() before.
# sys.argv[0] also fails, because it doesn't not always contains the path.
おまけとして、このアプローチでは、システムにインストールされているモジュールではなく、Python にモジュールを使用させることができます。
警告!現在のモジュールがファイル内にあるときに何が起こっているのか、私にはよくわかりませんegg
。それも多分失敗。
dirBar に__init__.py
ファイルがあることを確認してください。これにより、ディレクトリが Python パッケージになります。
サブディレクトリを Python パスに追加して、通常のスクリプトとしてインポートすることもできます。
import sys
sys.path.insert(0, <path to dirFoo>)
import Bar
import os
import sys
lib_path = os.path.abspath(os.path.join(__file__, '..', '..', '..', 'lib'))
sys.path.append(lib_path)
import mymodule
別のフォルダから.pyファイルをインポートする簡単なことをするだけです。
次のようなディレクトリがあるとします。
lib/abc.py
次に、名前の付いたlibフォルダーに空のファイルを保持します
__init__.py
そして、
from lib.abc import <Your Module name>
__init__.py
インポートモジュールの階層のすべてのフォルダーにファイルを保持します。
このようにプロジェクトを構成する場合:
src\
__init__.py
main.py
dirFoo\
__init__.py
Foo.py
dirBar\
__init__.py
Bar.py
次に、Foo.py から次のことができるはずです。
import dirFoo.Foo
または:
from dirFoo.Foo import FooObject
トムのコメントによると、これには、または検索パスsrc
を介してフォルダーにアクセスできる必要があります。site_packages
また、彼が言及しているように__init__.py
、そのパッケージ/ディレクトリにモジュールを最初にインポートすると、暗黙的にインポートされます。通常__init__.py
は単なる空のファイルです。
最も簡単な方法は、sys.path.append() を使用することです。
しかし、impモジュールにも興味があるかもしれません。内部インポート機能へのアクセスを提供します。
# mod_name is the filename without the .py/.pyc extention
py_mod = imp.load_source(mod_name,filename_path) # Loads .py file
py_mod = imp.load_compiled(mod_name,filename_path) # Loads .pyc file
これは、モジュールの名前がわからない場合にモジュールを動的にロードするために使用できます。
私は過去にこれを使用して、ユーザーがアプリケーション固有の機能を備えたスクリプトを記述し、そのスクリプトを特定のディレクトリにドロップするアプリケーションへのプラグイン タイプ インターフェイスを作成しました。
また、次の関数が役立つ場合があります。
imp.find_module(name[, path])
imp.load_module(name, file, pathname, description)
これは関連する PEP です。
http://www.python.org/dev/peps/pep-0328/
特に、dirFoo が dirBar から上のディレクトリであると仮定すると...
dirFoo\Foo.py で:
from ..dirBar import Bar
スクリプトを変更しない最も簡単な方法は、PYTHONPATH 環境変数を設定することです。sys.path は次の場所から初期化されるため:
とにかく走れ:
export PYTHONPATH=/absolute/path/to/your/module
以下に示すように、sys.path には上記のパスが含まれます。
print sys.path
['', '/absolute/path/to/your/module', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-linux2', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages/PIL', '/usr/lib/python2.7/dist-packages/gst-0.10', '/usr/lib/python2.7/dist-packages/gtk-2.0', '/usr/lib/pymodules/python2.7', '/usr/lib/python2.7/dist-packages/ubuntu-sso-client', '/usr/lib/python2.7/dist-packages/ubuntuone-client', '/usr/lib/python2.7/dist-packages/ubuntuone-control-panel', '/usr/lib/python2.7/dist-packages/ubuntuone-couch', '/usr/lib/python2.7/dist-packages/ubuntuone-installer', '/usr/lib/python2.7/dist-packages/ubuntuone-storage-protocol']
私の意見では、最良の選択は__ init __.pyをフォルダーに入れて、ファイルを呼び出すことです
from dirBar.Bar import *
既存の python パッケージと同じファイル名を使用すると何か問題が発生する可能性があるため、sys.path.append() の使用はお勧めしません。私はそれをテストしていませんが、それはあいまいです。
ただいじくり回していて、デプロイメントの問題を気にしない場合は、シンボリックリンクを使用して(ファイルシステムがそれをサポートしていると仮定して)、モジュールまたはパッケージを要求元のモジュールのフォルダーに直接表示できます。
ln -s (path)/module_name.py
また
ln -s (path)/package_name
__init__.py
注:「モジュール」は拡張子が.pyのファイルであり、「パッケージ」はファイル(空のファイルの場合もあります)を含むフォルダーです。使用法の観点から、モジュールとパッケージは同一です。どちらも、import
コマンドを介して要求されたとおりに、含まれている「定義とステートメント」を公開します。
from .dirBar import Bar
それ以外の:
from dirBar import Bar
別の dirBar がインストールされていて、foo.py リーダーを混乱させる可能性がある場合に備えて。
__init__.pyファイルを追加します。
dirFoo\
Foo.py
dirBar\
__init__.py
Bar.py
次に、このコードを Foo.py の先頭に追加します。
import sys
sys.path.append('dirBar')
import Bar
あなたが言及したように、通常、メイン スクリプトが実行されている場所に関連するモジュールを含むフォルダーにアクセスしたいので、それらをインポートするだけです。
解決:
スクリプトD:/Books/MyBooks.py
といくつかのモジュール (oldies.py など) があります。サブディレクトリからインポートする必要がありますD:/Books/includes
:
import sys,site
site.addsitedir(sys.path[0] + '\\includes')
print (sys.path) # Just verify it is there
import oldies
print('done')
に aを配置してoldies.py
、すべてが正常であることを確認します。sys.path
プログラムの起動時に初期化される Python 定義により、このリストの最初の項目 はpath[0]
、Python インタープリターを呼び出すために使用されたスクリプトを含むディレクトリであるため、この方法は常に機能します。
スクリプト ディレクトリが利用できない場合 (たとえば、インタプリタが対話的に呼び出された場合、またはスクリプトが標準入力から読み取られた場合)path[0]
は空の文字列であり、Python に最初に現在のディレクトリ内のモジュールを検索するように指示します。の結果として挿入されるエントリの前に、スクリプト ディレクトリが挿入されることに注意してくださいPYTHONPATH
。
相対 sys.path の例:
# /lib/my_module.py
# /src/test.py
if __name__ == '__main__' and __package__ is None:
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../lib')))
import my_module
この回答に基づいています。
慎重すぎると言われますが、ファイルがすべてのコンピューターで常に同じ場所にあると想定するのは安全ではないため、私は自分のファイルをよりポータブルにしたいと考えています。個人的には、コードで最初にファイル パスを検索します。私はLinuxを使用しているので、私の場合は次のようになります。
import os, sys
from subprocess import Popen, PIPE
try:
path = Popen("find / -name 'file' -type f", shell=True, stdout=PIPE).stdout.read().splitlines()[0]
if not sys.path.__contains__(path):
sys.path.append(path)
except IndexError:
raise RuntimeError("You must have FILE to run this program!")
もちろん、これらを一緒にパッケージ化する予定がない限り. しかし、その場合は、とにかく 2 つの個別のファイルは必要ありません。