925

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

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

4

22 に答える 22

1123
import a_module
print(a_module.__file__)

少なくともMac OS Xでは、ロードされた.pycファイルへのパスが実際に表示されます。したがって、次のことができると思います。

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

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

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

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

于 2008-10-29T23:57:13.760 に答える
327

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

公式文書

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'
于 2012-08-28T07:24:09.850 に答える
80

他の答えが言ったように、これを行う最良の方法は__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 

お役に立てれば。この警告により、提示された他のソリューションをテストする際に、多くの時間と混乱が生じました。

于 2011-06-20T19:05:40.220 に答える
62

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

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

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

使用上の注意__file__

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

import something
something.__file__ 

モジュールの絶対パスを返します。ただし、次のスクリプト foo.py があるとします。

#foo.py
print '__file__', __file__

「python foo.py」で呼び出すと、単純に「foo.py」が返されます。シバンを追加する場合:

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

./foo.py を使用して呼び出すと、'./foo.py' が返されます。別のディレクトリから呼び出して (たとえば、ディレクトリ bar に foo.py を配置)、次のいずれかを呼び出します。

python bar/foo.py

または、シバンを追加してファイルを直接実行します。

bar/foo.py

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

ディレクトリの検索

そこからディレクトリを取得するの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: 

つまり、空の文字列を返すため、(インポートされたモジュールのファイルとは対照的に)現在のファイルに使用する場合、これは信頼できないようです。これを回避するには、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.py を指すシンボリック リンク file_import_testing_link を作成します。

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)

素直に絶対パスを返します。現在実行中のスクリプトのパスを見つけるには:

inspect.getfile(inspect.currentframe())

(ありがとう @jbochi)

inspect.getabsfile(inspect.currentframe()) 

現在実行中のスクリプトの絶対パスを提供します (@Sadman_Sakib に感謝)。

于 2013-05-30T02:15:40.017 に答える
43

誰もこれについて話していない理由はわかりませんが、私にとって最も簡単な解決策はimp.find_module("modulename")を使用することです(ドキュメントはこちら):

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))

「検査」方法に対するこの方法の利点は、機能させるためにモジュールをインポートする必要がなく、入力に文字列を使用できることです。たとえば、別のスクリプトで呼び出されたモジュールをチェックするときに役立ちます。

編集

python3 では、importlibモジュールは次のことを行う必要があります。

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

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

最初に、sys.modules がチェックされ、モジュールが既にインポートされているかどうかが確認されます。もしそうなら、sys.modules[name]. スペックが返ってきました。それがたまたま None に設定されている場合、ValueError が発生します。モジュールが sys.modules にない場合、sys.meta_path は、ファインダーに与えられた「パス」の値で適切な仕様を検索します。仕様が見つからない場合は、何も返されません。

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

name および package 引数は、importlib.import_module() と同じように機能します。つまり、相対的なモジュール名 (先行ドット付き) が機能します。

于 2015-03-11T00:10:44.000 に答える
22

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

各モジュールには、__file__現在の場所からの相対パスを示す変数があります。

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

os.path.dirname(__file__)
于 2008-10-29T19:18:15.320 に答える
17
import os
path = os.path.abspath(__file__)
dir_path = os.path.dirname(path)
于 2010-12-13T17:35:17.707 に答える
15
import module
print module.__path__

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

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

ソース

于 2014-08-16T23:04:03.010 に答える
11

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

コマンドラインユーティリティに微調整できます。

python-which <package name>

ここに画像の説明を入力


作成/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
于 2015-08-15T16:27:18.247 に答える
6

だから私は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__))
于 2012-03-18T16:28:43.550 に答える
5

モジュールをインポートすると、多くの情報にアクセスできます。チェックアウトしてくださいdir(a_module)。パスに関しては、そのためのダンダーがあります: a_module.__path__. モジュール自体を印刷することもできます。

>>> import a_module
>>> print(dir(a_module))
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__']
>>> print(a_module.__path__)
['/.../.../a_module']
>>> print(a_module)
<module 'a_module' from '/.../.../a_module/__init__.py'>
于 2020-11-12T08:53:23.883 に答える
3

使用に関する唯一の注意点__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

コツは通話のor '.'後にありdirname()ます。dir を として設定します。これは、現在のディレクトリ.を意味し、パス関連の機能に対して有効なディレクトリです。

したがって、使用abspath()する必要はありません。ただし、とにかく使用する場合は、トリックは必要ありません。abspath()空のパスを受け入れ、それを現在のディレクトリとして適切に解釈します。

于 2014-08-15T01:22:39.707 に答える
1

これを「プログラム」で動的に実行したい場合は、次のコードを試してください。
要点は、「ハードコード」するモジュールの正確な名前がわからない場合があるということです。リストから選択されているか、__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'>

「グローバル」の問題を取り除こうとしましたが、うまくいかないケースが見つかりました 「execfile()」はPython 3でエミュレートできると思います これはプログラム内にあるため、メソッドまたはモジュールに簡単に配置できます再利用。

于 2015-01-14T01:23:25.097 に答える
1

Python パッケージのモジュール内から、パッケージと同じディレクトリにあるファイルを参照する必要がありました。元。

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 による投稿に基づいて、コードを修正しました。

于 2015-05-12T13:27:01.890 に答える
0

誰にとっても役立つ場合に備えて、簡単な bash スクリプトを次に示します。コードにできるように、環境変数を設定できるようにしたいだけですpushd

#!/bin/bash
module=${1:?"I need a module name"}

python << EOI
import $module
import os
print os.path.dirname($module.__file__)
EOI

シェルの例:

[root@sri-4625-0004 ~]# export LXML=$(get_python_path.sh lxml)
[root@sri-4625-0004 ~]# echo $LXML
/usr/lib64/python2.7/site-packages/lxml
[root@sri-4625-0004 ~]#
于 2020-02-10T17:51:18.237 に答える