Python에서 호출 함수 모듈의 __name__ 가져 오기


96

다음을 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

이 경우 호출 함수 모듈 ( 'myapp.foo') caller_name__name__속성 으로 설정 하고 싶습니다 . 어떻게 할 수 있습니까?


일부 다른 진입 점 스크립트가 bar.py ..를 호출하므로 그럴 caller_name수 없다고 가정합니다.__main__
Sridhar Ratnakumar

답변:


123

검사 모듈을 확인하십시오.

inspect.stack() 스택 정보를 반환합니다.

함수 내에서 inspect.stack()[1]호출자의 스택을 반환합니다. 거기에서 호출자의 함수 이름, 모듈 등에 대한 자세한 정보를 얻을 수 있습니다.

자세한 내용은 문서를 참조하십시오.

http://docs.python.org/library/inspect.html

또한 Doug Hellmann은 PyMOTW 시리즈에서 inspect 모듈에 대한 멋진 글을 작성했습니다.

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)

1
그렇다면 __name__모듈을 사용하여이 모듈 의 속성을 어떻게 얻 inspect습니까? 예를 들어, 위의 예에서 어떻게 돌아가나요 myapp.foo(아님 myapp/foo.py)? SO에 게시하기 전에 이미 inspect 모듈을 사용해 보았습니다.
Sridhar Ratnakumar

6
이것은 import 후크와 이상하게 상호 작용하고 ironpython에서 작동하지 않으며 jython에서 놀라운 방식으로 작동 할 수 있습니다. 이런 마법을 피할 수 있다면 가장 좋습니다.
Glyph

2
또한 스택 프레임에 대한 참조를 유지하면 Python의 GC가 올바르게 작동하지 않을 수 있습니다. 여기에서 경고를 참조하십시오 : docs.python.org/library/inspect.html#the-interpreter-stack
Kamil Kisiel

6
호출자 함수가 데코 레이팅 된 경우 (@ ...) inspect.stack()[2]실제 호출자 를 위해 액세스해야 합니다.
Amir Ali Akbari 2013

또한 pyinstaller를 사용하여 Python 코드를 exe로 컴파일 할 때이 논리가 제대로 작동하지 않습니다.
panofish 2014 년

19

비슷한 문제에 직면 하여 sys 모듈의 sys._current_frames () 에는 적어도 특정 사용 사례에서 inspect를 가져올 필요없이 도움이 될 수있는 흥미로운 정보가 포함되어 있음을 발견했습니다 .

>>> 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을 사용할 수도 있습니다. 이 방법의 한계와주의 사항은 확실하지 않지만 (다중 스레드가 문제가 될 가능성이 높음) 제 경우에는 사용하려고합니다.


2
참고 : inspect.stack 코드는 pyinstaller를 사용하여 exe로 컴파일 한 후 실패하지만 sys._current_frames WORKS FINE ...을 사용하므로 이것이 저에게 선호되는 기술입니다.
panofish 2014 년

7
(모든 스레드에 대해 프레임 매핑을 반환하는 btw)를 sys._getframe(1)호출하는 대신으로 이전 프레임을 얻는 것이 더 쉽다고 생각합니다 sys._current_frames().
hooblei

감사합니다 hooblei, 아직 테스트하지는 않았지만 멀티 스레드 상황에 매우 유용합니다.
Louis LC

내가 사용하는 것을 선호 inspect.currentframe()대신 sys._current_frames().values()[0].
Aran-Fey

3

권장하지 않지만 다음 방법으로 목표를 달성 할 수 있습니다.

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)

7
파일 이름과 동일하지 않습니다__name__
스리 Ratnakumar
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.