web-dev-qa-db-ja.com

モジュールのパスを取得する方法

モジュールが変更されたかどうかを検出したい今、inotifyを使うのは簡単です、あなたはあなたがから通知を得たいディレクトリを知る必要があるだけです。

Pythonでモジュールのパスを取得するにはどうすればいいですか?

622
Cheery
import a_module
print(a_module.__file__)

実際には、少なくともMac OS Xでは、ロードされた.pycファイルへのパスを教えてくれるでしょう。

import os
path = os.path.dirname(a_module.__file__)

あなたも試すことができます:

path = os.path.abspath(a_module.__file__)

モジュールのディレクトリを取得します。

728
orestis

Pythonにはinspectモジュールがあります。

公式文書

Inspectモジュールは、モジュール、クラス、メソッド、関数、トレースバック、フレームオブジェクト、コードオブジェクトなどのライブオブジェクトに関する情報を取得するのに役立つ便利な関数をいくつか提供します。たとえば、クラスの内容を調べたり、メソッドのソースコードを取得したり、関数の引数リストを抽出してフォーマットしたり、詳細なトレースバックを表示するために必要なすべての情報を取得したりするのに役立ちます。

例:

>>> import os
>>> import inspect
>>> inspect.getfile(os)
'/usr/lib64/python2.7/os.pyc'
>>> inspect.getfile(inspect)
'/usr/lib64/python2.7/inspect.pyc'
>>> os.path.dirname(inspect.getfile(inspect))
'/usr/lib64/python2.7'
220
SummerBreeze

他の答えが言っているように、これをする最もよい方法は__file__を使うことです(以下に再び示されています)。ただし、重要な注意点があります。つまり、モジュールを単独で(つまり__file__として)実行している場合、__main__は存在しません。

たとえば、2つのファイルがあるとします(どちらもPYTHONPATHにあります)。

#/path1/foo.py
import bar
print(bar.__file__)

そして

#/path2/bar.py
import os
print(os.getcwd())
print(__file__)

Foo.pyを実行すると出力が得られます。

/path1        # "import bar" causes the line "print(os.getcwd())" to run
/path2/bar.py # then "print(__file__)" runs
/path2/bar.py # then the import statement finishes and "print(bar.__file__)" runs

ただし、bar.pyを単独で実行しようとすると、次のようになります。

/path2                              # "print(os.getcwd())" still works fine
Traceback (most recent call last):  # but __file__ doesn't exist if bar.py is running as main
  File "/path2/bar.py", line 3, in <module>
    print(__file__)
NameError: name '__file__' is not defined 

お役に立てれば。提示された他の解決策をテストする間、この警告は私に多くの時間と混乱を要しました。

63
mcstrother

私はこの質問についてもいくつかのバリエーションに取り組みます。

  1. 呼び出されたスクリプトのパスを見つける
  2. 現在実行中のスクリプトのパスを見つける
  3. 呼び出されたスクリプトのディレクトリを見つける

(これらの質問のいくつかはSOについて尋ねられましたが、重複して閉じられ、ここでリダイレクトされました。)

__file__を使用する際の注意事項

インポートしたモジュールの場合:

import something
something.__file__ 

モジュールの 絶対 パスを返します。しかし、次のようなスクリプトがあるとします。

#foo.py
print '__file__', __file__

'python foo.py'で呼び出すと、単に 'foo.py'が返されます。 Shebangを追加した場合

#!/usr/bin/python 
#foo.py
print '__file__', __file__

そしてそれを./foo.pyを使って呼び出すと、 './ foo.py'が返されます。別のディレクトリからそれを呼び出す(例えば、ディレクトリバーにfoo.pyを入れる)、そしてどちらかを呼び出す

python bar/foo.py

またはShebangを追加してファイルを直接実行します。

bar/foo.py

'bar/foo.py'( relative パス)を返します。

ディレクトリを探す

そこからディレクトリを取得するために、os.path.dirname(__file__)もトリッキーになることがあります。少なくとも私のシステムでは、ファイルと同じディレクトリから呼び出すと空の文字列を返します。例.

# foo.py
import os
print '__file__ is:', __file__
print 'os.path.dirname(__file__) is:', os.path.dirname(__file__)

出力されます:

__file__ is: foo.py
os.path.dirname(__file__) is: 

言い換えれば、空の文字列を返すので、(インポートされたモジュールの file ではなく)現在の file にそれを使用したい場合、これは信頼できません。これを回避するために、abspathへの呼び出しでそれをラップすることができます。

# foo.py
import os
print 'os.path.abspath(__file__) is:', os.path.abspath(__file__)
print 'os.path.dirname(os.path.abspath(__file__)) is:', os.path.dirname(os.path.abspath(__file__))

これは次のように出力されます。

os.path.abspath(__file__) is: /home/user/bar/foo.py
os.path.dirname(os.path.abspath(__file__)) is: /home/user/bar

Abspath()はシンボリックリンクを解決しないことに注意してください。これを行いたい場合は、代わりにrealpath()を使用してください。たとえば、シンボリックリンクfile_import_testing_linkをfile_import_testing.pyを指すようにします。その内容は次のとおりです。

import os
print 'abspath(__file__)',os.path.abspath(__file__)
print 'realpath(__file__)',os.path.realpath(__file__)

実行すると、絶対パスが次のように出力されます。

abspath(__file__) /home/user/file_test_link
realpath(__file__) /home/user/file_test.py

file_import_testing_link - > file_import_testing.py

検査を使用する

@SummerBreezeは inspect モジュールの使用について言及しています。

これはうまく機能しているようで、インポートされたモジュールに対しては非常に簡潔です。

import os
import inspect
print 'inspect.getfile(os) is:', inspect.getfile(os)

素直に絶対パスを返します。しかし、現在実行中のスクリプトのパスを見つけるために、私はそれを使用する方法を見ませんでした。

34
jpgeek

私は誰もこれについて話していない理由はわかりませんが、私にとって最も簡単な解決策は imp.find_module( "modulename") (documentation here )を使うことです:

import imp
imp.find_module("os")

これは、2番目の位置にあるパスを持つタプルを与えます。

(<open file '/usr/lib/python2.7/os.py', mode 'U' at 0x7f44528d7540>,
'/usr/lib/python2.7/os.py',
('.py', 'U', 1))

このメソッドが「検査」メソッドよりも優れている点は、モジュールを機能させるためにモジュールをインポートする必要がないことと、入力に文字列を使用できることです。たとえば、他のスクリプトで呼び出されたモジュールをチェックするときに役立ちます。

_ edit _

Python3では、importlibモジュールは次のことをするはずです。

importlib.util.find_specのドキュメント:

指定されたモジュールの仕様を返します。

まず、sys.modulesをチェックして、モジュールがすでにインポートされているかどうかを確認します。もしそうなら、sys.modules [name] . spec が返されます。それがたまたまNoneに設定されている場合、ValueErrorが送出されます。モジュールがsys.modulesにない場合、sys.meta_pathがファインダに与えられた 'path'の値で適切なspecを探すために検索されます。仕様が見つからない場合は、何も返されません。

名前がサブモジュール用(ドットを含む)の場合は、親モジュールが自動的にインポートされます。

名前とパッケージの引数はimportlib.import_module()と同じように機能します。つまり、相対的なモジュール名(先頭にドットが付いているもの)が機能します。

25
PlasmaBinturong

これは些細なことでした。

各モジュールは、あなたが現在いる場所からの相対パスを示す__file__変数を持っています。

したがって、モジュールがそれを通知するためのディレクトリを取得するのは簡単です。

os.path.dirname(__file__)
18
Cheery
import os
path = os.path.abspath(__file__)
dir_path = os.path.dirname(path)
17
vinoth

コマンドラインユーティリティ

あなたはそれをコマンドラインユーティリティに微調整することができます、

python-which <package name>

enter image description here


/usr/local/bin/python-whichを作成する

#!/usr/bin/env python

import importlib
import os
import sys

args = sys.argv[1:]
if len(args) > 0:
    module = importlib.import_module(args[0])
    print os.path.dirname(module.__file__)

実行可能にする

Sudo chmod +x /usr/local/bin/python-which
9
Jossef Harush
import module
print module.__path__

パッケージはもう1つの特別な属性__path__をサポートします。これは、そのファイルのコードが実行される前に、パッケージの__init__.pyを保持するディレクトリの名前を含むリストに初期化されます。この変数は変更可能です。そうすることは、パッケージに含まれるモジュールとサブパッケージの今後の検索に影響します。

この機能はあまり必要ではありませんが、パッケージに含まれる一連のモジュールを拡張するために使用できます。

出典

7
Lukas Greblikas

だから私はpy2exeでこれをやろうとするのにかなりの時間を費やした。問題はそれがpythonスクリプトとして実行されているかpy2exe実行可能ファイルとして実行されているかにかかわらずスクリプトのベースフォルダを得ることだった。また、現在のフォルダから実行されているのか、別のフォルダから実行されているのか(これが最も難しい)システムのパスから実行されているのかを確認することもできます。

最終的に私はこのアプローチを採用しました。sys.frozenをpy2exeで実行することの指標として使用しました。

import os,sys
if hasattr(sys,'frozen'): # only when running in py2exe this exists
    base = sys.prefix
else: # otherwise this is a regular python script
    base = os.path.dirname(os.path.realpath(__file__))
7
uri

あなたは単にあなたのモジュールをインポートしてその名前を打つことができますそしてあなたはそのフルパスを得るでしょう

>>> import os
>>> os
<module 'os' from 'C:\\Users\\Hassan Ashraf\\AppData\\Local\\Programs\\Python\\Python36-32\\lib\\os.py'>
>>>
4
Hassan Ashraf

__file__を使用することに関する唯一の注意点が、現在の相対ディレクトリが空白の場合(つまり、スクリプトと同じディレクトリからスクリプトとして実行している場合)は、次のような簡単な解決策になります。

import os.path
mydir = os.path.dirname(__file__) or '.'
full  = os.path.abspath(mydir)
print __file__, mydir, full

そしてその結果:

$ python teste.py 
teste.py . /home/user/work/teste

トリックはdirname()呼び出しの後のor '.'にあります。これはdirを.として設定します。これは 現在のディレクトリ を意味し、パス関連の関数には有効なディレクトリです。

したがって、abspath()を使うことは本当に必要ではありません。しかし、それを使用するのであれば、トリックは必要ありません。abspath()は空白パスを受け入れ、それを現在のディレクトリとして正しく解釈します。

3
MestreLion

私は1つの一般的なシナリオ(Python 3)に貢献し、それに対するいくつかのアプローチを探りたいです。

組み込み関数 open() は、最初の引数として相対パスまたは絶対パスを受け入れます。相対パスは現在の作業ディレクトリからの相対パスとして扱われますが、絶対パスをファイルに渡すことをお勧めします。

簡単に言うと、次のコードでスクリプトファイルを実行した場合、それはではありません)example.txtファイルは、スクリプトファイルと同じディレクトリに作成されます。

with open('example.txt', 'w'):
    pass

このコードを修正するには、スクリプトへのパスを取得して絶対パスにする必要があります。パスを絶対パスにするには、 os.path.realpath() 関数を使用します。スクリプトへのパスを取得するために、さまざまなパス結果を返す一般的な関数がいくつかあります。

  • os.getcwd()
  • os.path.realpath('example.txt')
  • sys.argv[0]
  • __file__

両方の関数 os.getcwd() および os.path.realpath() は、現在の作業ディレクトリに基づいてパス結果を返します。私たちが望むものではありません。 sys.argv リストの最初の要素は、リストをルートスクリプト自体で呼び出すか、そのモジュールのいずれかで呼び出すかにかかわらず、ルートスクリプトのパス(実行するスクリプト)です。 。状況によっては便利になるかもしれません。 __file__ 変数には、それが呼び出されたモジュールのパスが含まれています。


次のコードは、スクリプトと同じディレクトリにファイルexample.txtを正しく作成します。

filedir = os.path.dirname(os.path.realpath(__file__))
filepath = os.path.join(filedir, 'example.txt')

with open(filepath, 'w'):
    pass
3
Jeyekomon

Pythonパッケージのモジュール内から、私はpackageと同じディレクトリにあるファイルを参照しなければなりませんでした。例.

some_dir/
  maincli.py
  top_package/
    __init__.py
    level_one_a/
      __init__.py
      my_lib_a.py
      level_two/
        __init__.py
        hello_world.py
    level_one_b/
      __init__.py
      my_lib_b.py

そのため、上記では、top_packageとmaincli.pyが同じディレクトリにあることを確認しながら、my_lib_a.pyモジュールからmaincli.pyを呼び出す必要がありました。これがmaincli.pyへのパスを取得する方法です。

import sys
import os
import imp


class ConfigurationException(Exception):
    pass


# inside of my_lib_a.py
def get_maincli_path():
    maincli_path = os.path.abspath(imp.find_module('maincli')[1])
    # top_package = __package__.split('.')[0]
    # mod = sys.modules.get(top_package)
    # modfile = mod.__file__
    # pkg_in_dir = os.path.dirname(os.path.dirname(os.path.abspath(modfile)))
    # maincli_path = os.path.join(pkg_in_dir, 'maincli.py')

    if not os.path.exists(maincli_path):
        err_msg = 'This script expects that "maincli.py" be installed to the '\
        'same directory: "{0}"'.format(maincli_path)
        raise ConfigurationException(err_msg)

    return maincli_path

PlasmaBinturongによる投稿に基づいて、私はコードを修正しました。

1
Al Conrad

「プログラム」でこれを動的に行いたい場合は、次のコードを試してください。
私のポイントは、あなたがそれを "ハードコード"するためのモジュールの正確な名前を知らないかもしれないということです。リストから選択されているか、__ file__を使用するために現在実行されていない可能性があります。

(私は知っている、それはPython 3ではうまくいかないだろう)

global modpath
modname = 'os' #This can be any module name on the fly
#Create a file called "modname.py"
f=open("modname.py","w")
f.write("import "+modname+"\n")
f.write("modpath = "+modname+"\n")
f.close()
#Call the file with execfile()
execfile('modname.py')
print modpath
<module 'os' from 'C:\Python27\lib\os.pyc'>

私は "global"の問題を取り除こうとしましたが、それがうまく行かなかったケースを見つけました。再利用.

1
Robin Randall

スクリプトからの絶対パスを知りたい場合は、 Path objectを使用します。

from pathlib import Path

print(Path().absolute())
print(Path().resolve('.'))
print(Path().cwd())

cwd()メソッド

現在のディレクトリを表す新しいパスオブジェクトを返します(os.getcwd()によって返される)。

resolve()メソッド

シンボリックリンクを解決して、パスを絶対パスにします。新しいパスオブジェクトが返されます。

1
Vlad Bezden

モジュールからパッケージのルートパスを取得したい場合は、次のように動作します(Python 3.6でテスト済み)。

from . import __path__ as ROOT_PATH
print(ROOT_PATH)

メインの__init__.pyパスは、代わりに__file__を使用して参照することもできます。

お役に立てれば!

0
fr_andres