相対パスを指定して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
Tomのコメントによると、これは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 *
Sys.path.append()を使用することはお勧めできません。既存のpythonパッケージと同じファイル名を使用すると、問題が発生する可能性があるためです。私はそれをテストしていませんが、それはあいまいになります。
ちょっと手を加えていて展開の問題を気にしないのであれば、ファイルシステムがそれをサポートしていると仮定してシンボリックリンクを使用して、要求しているモジュールのフォルダに直接モジュールまたはパッケージを表示できます。
ln -s (path)/module_name.py
または
ln -s (path)/package_name
注: "module"は拡張子が.pyのファイル、 "package"はファイル__init__.py
を含むフォルダーです(空のファイルでもかまいません)。使用法の観点からは、モジュールとパッケージは同一です。どちらもimport
コマンドを介して要求されたときに含まれる「定義とステートメント」を公開します。
from .dirBar import Bar
の代わりに:
from dirBar import Bar
万が一別のdirBarがインストールされていてfoo.pyリーダーを混乱させる可能性があります。
この場合、Bar.pyをFoo.pyにインポートするには、まずこれらのフォルダを次のようにPythonパッケージに変換します。
dirFoo\
__init__.py
Foo.py
dirBar\
__init__.py
Bar.py
それなら私はFoo.pyでこうするでしょう:
from .dirBar import Bar
名前空間をBar .whateverのようにしたい場合、または
from . import dirBar
名前空間dirBar.Bar .何でもが必要な場合。この2番目のケースは、dirBarパッケージの下にさらにモジュールがある場合に役立ちます。
__init__.py ファイルを追加します。
dirFoo\
Foo.py
dirBar\
__init__.py
Bar.py
次に、このコードをFoo.pyの先頭に追加します。
import sys
sys.path.append('dirBar')
import Bar
相対sys.pathの例:
# /lib/my_module.py
# /src/test.py
if __== '__main__' and __package__ is None:
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../lib')))
import my_module
に基づいて これ 答え。
あなたが言及したように、通常、あなたはあなたのメインスクリプトが実行されている場所に関連してあなたのモジュールを含むフォルダにアクセスしたいので、あなたはそれらをインポートするだけです。
溶液:
私は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')
をoldies.py
に配置して、すべてが問題ないことを確認します。プログラムの起動時に初期化されるPython定義sys.path
によって、このリストの最初の項目path[0]
は、Pythonインタプリタを呼び出すために使用されたスクリプトを含むディレクトリであるため、この方法は常に機能します。
スクリプトディレクトリが利用できない場合(たとえば、インタプリタが対話的に呼び出された場合、またはスクリプトが標準入力から読み込まれた場合)、path[0]
は空の文字列で、最初に現在のディレクトリ内のモジュールを検索します。 PYTHONPATH
の結果としてエントリが挿入される前に、スクリプトディレクトリが挿入されていることに注意してください。
別の解決策は py-require パッケージをインストールしてからFoo.py
で以下を使うことです。
import require
Bar = require('./dirBar/Bar')
単に使うことができます:from Desktop.filename import something
例:
ファイルはディレクトリ
test.py
内のUsers/user/Desktop
という名前で、反転をインポートします。
コード:
from Desktop.test import *
ただし、必ずそのディレクトリに "__init__.py
"という名前の空のファイルを作成してください。
これは、相対パスを使用して、上のレベルからファイルをインポートする方法です。
基本的には、作業ディレクトリを1レベル上(または任意の相対位置)に移動し、それをパスに追加してから、作業ディレクトリを開始位置に戻します。
#to import from one level above:
cwd = os.getcwd()
os.chdir("..")
below_path = os.getcwd()
sys.path.append(below_path)
os.chdir(cwd)
標準ライブラリのpkgutilモジュールを見てください。それはあなたが望むことをするのを助けるかもしれません。
私はPythonについては経験がないので、もし私の言葉に何か問題があるのなら、ただ私に言ってください。ファイル階層が次のようになっているとします。
project\
module_1.py
module_2.py
module_1.py
はfunc_1()
、 module_2.py と呼ばれる関数を定義します。
from module_1 import func_1
def func_2():
func_1()
if __== '__main__':
func_2()
cmdでpython module_2.py
を実行すると、func_1()
で定義されているとおりに実行されます。それが通常同じ階層ファイルをインポートする方法です。しかし、あなたがfrom .module_1 import func_1
にmodule_2.py
を書くとき、pythonインタプリタはNo module named '__main__.module_1'; '__main__' is not a package
を言うでしょう。それでこれを直すために、私達はちょうど行った変更を保持し、そして両方のモジュールをパッケージに移し、そしてmodule_2.py
を実行するための呼び出し側として三番目のモジュールを作るだけです。
project\
package_1\
module_1.py
module_2.py
main.py
main.py :
from package_1.module_2 import func_2
def func_3():
func_2()
if __== '__main__':
func_3()
しかし、.
のmodule_1
の前にmodule_2.py
を追加するのは、それをしないでmain.py
を実行すると、pythonインタプリタがNo module named 'module_1'
と言うことになるので、module_1.py
はmodule_2.py
のすぐ横にあります。 module_1.py
のfunc_1()
に何かをさせます。
def func_1():
print(__name__)
その__name__
は、誰がfunc_1を呼び出したかを記録します。これで.
をmodule_1
の前に置き、main.py
を実行します。これはpackage_1.module_1
ではなくmodule_1
を出力します。これは、func_1()
を呼び出す人がmain.py
と同じ階層にあることを示し、.
はmodule_1
がmodule_2.py
自体と同じ階層にあることを意味します。したがって、ドットがない場合、main.py
はそれ自体と同じ階層でmodule_1
を認識しますが、package_1
は認識できますが、その下にあるものは認識できません。
それでは少し複雑にしましょう。 config.ini
があり、モジュールはそれを読むための関数を 'main.py'と同じ階層で定義しています。
project\
package_1\
module_1.py
module_2.py
config.py
config.ini
main.py
そしてやむを得ない理由で、あなたはmodule_2.py
でそれを呼ばなければなりません、それでそれは上の階層からインポートしなければなりません。module_2.py :
import ..config
pass
2つのドットは上位階層からのインポートを意味します(3つのドットが上位より上位にアクセスする、など)。今main.py
を実行します、インタプリタは言うでしょう:ValueError:attempted relative import beyond top-level package
。ここにある "トップレベルパッケージ"はmain.py
です。 config.py
がmain.py
の横にあるという理由だけで、それらは同じ階層にあります、config.py
はmain.py
の「下」ではない、またはmain.py
によって「導かれる」わけではないので、main.py
を超えています。これを解決するための最も簡単な方法は次のとおりです。
project\
package_1\
module_1.py
module_2.py
config.py
config.ini
main.py
これはプロジェクトファイルの階層を整理するという原則と一致していると思います。さまざまな機能を持つモジュールをさまざまなフォルダに整理し、一番上の呼び出し元を外側に残すだけで、いつでもインポートできます。