myapp/foo.py
に含まれるもの:
def info(msg):
caller_name = ????
print '[%s] %s' % (caller_name, msg)
そして、myapp/bar.py
に含まれるもの:
import foo
foo.info('Hello') # => [myapp.bar] Hello
が欲しいです caller_name
に設定される__name__
この場合の呼び出し関数モジュールの属性(「myapp.foo」)。これをどのように行うことができますか?
検査モジュールをチェックアウトします。
inspect.stack()
はスタック情報を返します。
関数内では、inspect.stack()[1]
は呼び出し元のスタックを返します。そこから、呼び出し元の関数名、モジュールなどに関する詳細情報を取得できます。
詳細については、ドキュメントを参照してください。
http://docs.python.org/library/inspect.html
また、Doug Hellmannが彼のPyMOTWシリーズの検査モジュールの素晴らしい記事を書いています。
http://pymotw.com/2/inspect/index.html#module-inspect
編集:ここにあなたが望むものを行ういくつかのコードがあります、私は思う:
def info(msg):
frm = inspect.stack()[1]
mod = inspect.getmodule(frm[0])
print '[%s] %s' % (mod.__name__, msg)
同様の問題に直面して、sysモジュールのsys._current_frames()には、少なくとも特定のユースケースで、検査をインポートする必要なく、役立つ情報が含まれていることがわかりました。
>>> sys._current_frames()
{4052: <frame object at 0x03200C98>}
その後、f_backを使用して「上に移動」できます。
>>> f = sys._current_frames().values()[0]
>>> # for python3: f = list(sys._current_frames().values())[0]
>>> print f.f_back.f_globals['__file__']
'/base/data/home/apps/apricot/1.6456165165151/caller.py'
>>> print f.f_back.f_globals['__name__']
'__main__'
上記のMark Roddyが提案したように、ファイル名にはf.f_back.f_code.co_filenameも使用できます。この方法の制限と注意点はわかりません(複数のスレッドが問題になる可能性が高い)が、私の場合はそれを使用するつもりです。
これはお勧めしませんが、次の方法で目標を達成できます。
def caller_name():
frame=inspect.currentframe()
frame=frame.f_back.f_back
code=frame.f_code
return code.co_filename
次に、次のように既存のメソッドを更新します。
def info(msg):
caller = caller_name()
print '[%s] %s' % (caller, msg)