web-dev-qa-db-ja.com

相対パスからモジュールをインポートする

相対パスを指定してPythonモジュールをインポートする方法

たとえば、dirFooFoo.pydirBarが含まれ、dirBarBar.pyが含まれる場合、Bar.pyFoo.pyにインポートするにはどうすればよいですか。

これが視覚的な表現です。

dirFoo\
    Foo.py
    dirBar\
        Bar.py

FooBarをインクルードしたいのですが、フォルダ階層の再構築はできません。

728
Jude Allred

両方のディレクトリが本物の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ファイルの中にあるとき、何が起こっているのか、私は本当にわかりません。それもおそらく失敗します。

324
sorin

DirBarが__init__.pyファイルを持っていることを確認してください - これはディレクトリをPythonパッケージにします。

320
S.Lott

通常のスクリプトとしてインポートするように、サブディレクトリをPythonパスに追加することもできます。

import sys
sys.path.insert(0, <path to dirFoo>)
import Bar
250
Andrew Cox
import os
import sys
lib_path = os.path.abspath(os.path.join(__file__, '..', '..', '..', 'lib'))
sys.path.append(lib_path)

import mymodule
114
lefakir

別のフォルダから.pyファイルをインポートするために簡単なことをするだけです。

次のようなディレクトリがあるとしましょう。

lib/abc.py

それからlibフォルダに空のファイルを名前を付けて保存するだけです。

__init__.py

そして使う

from lib.abc import <Your Module name>

インポートモジュールの階層のすべてのフォルダに__init__.pyファイルを保存します。

97

プロジェクトをこのように構成すると、

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は単に空のファイルです。

78
bouvard

最も簡単な方法は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)
44
monkut

これは関連するPEPです。

http://www.python.org/dev/peps/pep-0328/

特に、dirFooがdirBarから上のディレクトリであると仮定すると...

DirFoo\Foo.pyに:

from ..dirBar import Bar
43
Peter Crabtree

スクリプトを変更しないで最も簡単な方法は、PYTHONPATH環境変数を設定することです。 sys.pathは次の場所から初期化されるため、

  1. 入力スクリプトを含むディレクトリ(または現在のディレクトリ)。
  2. PYTHONPATH(シェル変数PATHと同じ構文のディレクトリ名のリスト)。
  3. インストール依存のデフォルト。

とにかく走れ:

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']
22
James Gan

私の意見では、最良の選択は __ init __.py をフォルダーに入れて、ファイルを次のように呼び出すことです。

from dirBar.Bar import *

Sys.path.append()を使用することはお勧めできません。既存のpythonパッケージと同じファイル名を使用すると、問題が発生する可能性があるためです。私はそれをテストしていませんが、それはあいまいになります。

12
jhana

Linuxユーザーのための手っ取り早い方法

ちょっと手を加えていて展開の問題を気にしないのであれば、ファイルシステムがそれをサポートしていると仮定してシンボリックリンクを使用して、要求しているモジュールのフォルダに直接モジュールまたはパッケージを表示できます。

ln -s (path)/module_name.py

または

ln -s (path)/package_name

注: "module"は拡張子が.pyのファイル、 "package"はファイル__init__.pyを含むフォルダーです(空のファイルでもかまいません)。使用法の観点からは、モジュールとパッケージは同一です。どちらもimportコマンドを介して要求されたときに含まれる「定義とステートメント」を公開します。

参照してください: http://docs.python.org/2/tutorial/modules.html

11
nobar
from .dirBar import Bar

の代わりに:

from dirBar import Bar

万が一別のdirBarがインストールされていてfoo.pyリーダーを混乱させる可能性があります。

9
jgomo3

この場合、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パッケージの下にさらにモジュールがある場合に役立ちます。

8
Al Conrad

__init__.py ファイルを追加します。

dirFoo\
    Foo.py
    dirBar\
        __init__.py
        Bar.py

次に、このコードをFoo.pyの先頭に追加します。

import sys
sys.path.append('dirBar')
import Bar
6
Josh

相対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

に基づいて これ 答え。

5
Der_Meister

あなたが言及したように、通常、あなたはあなたのメインスクリプトが実行されている場所に関連してあなたのモジュールを含むフォルダにアクセスしたいので、あなたはそれらをインポートするだけです。

溶液:

私は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の結果としてエントリが挿入される前に、スクリプトディレクトリが挿入されていることに注意してください。

4
Avenida Gez

別の解決策は py-require パッケージをインストールしてからFoo.pyで以下を使うことです。

import require
Bar = require('./dirBar/Bar')
3
Niklas R

単に使うことができます:from Desktop.filename import something

例:

ファイルはディレクトリtest.py内のUsers/user/Desktopという名前で、反転をインポートします。

コード:

from Desktop.test import *

ただし、必ずそのディレクトリに "__init__.py"という名前の空のファイルを作成してください。

3
0x1996

これは、相対パスを使用して、上のレベルからファイルをインポートする方法です。

基本的には、作業ディレクトリを1レベル上(または任意の相対位置)に移動し、それをパスに追加してから、作業ディレクトリを開始位置に戻します。

#to import from one level above:
cwd = os.getcwd()
os.chdir("..")
below_path =  os.getcwd()
sys.path.append(below_path)
os.chdir(cwd)
2
Justin Muller

標準ライブラリのpkgutilモジュールを見てください。それはあなたが望むことをするのを助けるかもしれません。

2
Mihail Mihaylov

私はPythonについては経験がないので、もし私の言葉に何か問題があるのなら、ただ私に言ってください。ファイル階層が次のようになっているとします。

project\
    module_1.py 
    module_2.py

module_1.pyfunc_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_1module_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.pymodule_2.pyのすぐ横にあります。 module_1.pyfunc_1()に何かをさせます。

def func_1():
    print(__name__)

その__name__は、誰がfunc_1を呼び出したかを記録します。これで.module_1の前に置き、main.pyを実行します。これはpackage_1.module_1ではなくmodule_1を出力します。これは、func_1()を呼び出す人がmain.pyと同じ階層にあることを示し、.module_1module_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.pymain.pyの横にあるという理由だけで、それらは同じ階層にあります、config.pymain.pyの「下」ではない、またはmain.pyによって「導かれる」わけではないので、main.pyを超えています。これを解決するための最も簡単な方法は次のとおりです。

project\
    package_1\
        module_1.py
        module_2.py
    config.py
    config.ini
main.py

これはプロジェクトファイルの階層を整理するという原則と一致していると思います。さまざまな機能を持つモジュールをさまざまなフォルダに整理し、一番上の呼び出し元を外側に残すだけで、いつでもインポートできます。

0
OmouYue