파이썬에서 현재 모듈의 속성에 대한 참조를 얻는 방법


119

내가하려는 것은 명령 줄에서 다음과 같이 보일 것입니다.

>>> import mymodule
>>> names = dir(mymodule)

자체 mymodule내에서 정의 된 모든 이름에 대한 참조를 어떻게 얻을 수 mymodule있습니까?

이 같은:

# mymodule.py
names = dir(__thismodule__)

답변:


135

globals () 사용

globals () — 현재 전역 심볼 테이블을 나타내는 사전을 반환합니다. 이것은 항상 현재 모듈의 딕셔너리입니다 (함수 또는 메서드 내에서, 호출되는 모듈이 아니라 정의 된 모듈입니다).

http://docs.python.org/library/functions.html#globals


4
정의 모듈 대신 호출 모듈의 gloabals ()에 액세스하는 방법이 있습니까?
dimo414

9
traceback 모듈 ( docs.python.org/library/traceback.html ) 에서 호출자의 전역을 가져 오려고 시도 할 수 있지만 이것은 어두운 마법 영역에 들어가고 있습니다. 뭘하려고하는지 모르겠지만 필요한 경우 디자인을 다시 생각할 수 있습니다.
Maciej Pasternacki

"X가 필요합니다 (Y를 완료하려면)-> X가 필요하지 않습니다. Z가 필요합니다."의 전형적인 경우입니다. 그래도 X가 필요합니다! 어떤 범죄가, 난 그냥이 즐겁게, 그리고 대부분의 대답은 투표 찾을 것은 나에게 응답 I 필요 : 제공
pawamoy

globals ()는 호출되는 컨텍스트에 따라 잘못된 결과를 반환 할 수 있습니다. 예를 들어, 클래스 함수에서 호출하면 현재 모듈 컨텍스트가 아니라 클래스에 연결된 전역 컨텍스트를 반환합니다. 이는 상당히 다른 것입니다. 자유 함수에서 호출하더라도 함수를 가져온 방법에 따라 다른 모듈 전역 컨텍스트를 반환 할 수 있습니다.
Andry 2011

163

앞서 언급했듯이 globals는 모듈에 정의 된 이름 목록을 제공하는 dir ()과는 반대로 사전을 제공합니다. 내가 일반적으로 이것을 보는 방식은 다음과 같습니다.

import sys
dir(sys.modules[__name__])

2
sys.modules에 나열되지 않는 것처럼 보이기 때문에 ' 메인 '모듈 (터미널에서 실행되는 모듈이 호출 됨) 에서는 작동하지 않는다는 주석을 추가하려고 했지만 실제로 작동합니다. :)
markm 2011

그러나 ipdb에서 작동하지 않는 것 같습니다 ( "import ipdb; ipdb.set_trace ()"를 파일에 삽입).
gatoatigrado

9
우수한! 이것은 현재 모듈의 독 스트링을 사용 메시지로 사용할 수있게 해주었습니다 sys.modules[__name__].__doc__.
george

그리고 슈퍼 해키를 얻으려면. operators.attrgetter('module.attribute')(sys.modules[__name__])-알다시피, 만약 당신이 미친 짓을한다면, 사람들은 문자열에서 동적으로 패키지를 임포트하는 것을 좋아하지 말라고 말합니다. 그리고 그 클래스 나 그 어떤 것에도 속하지 않는 동안 원숭이 패치를합니다 ...
casey

2
george의 주석을 읽는 모든 사람 : sys.modules[__name__].__doc__== __doc__현재 네임 스페이스에 정의되어 있습니다. 따라서 자체 속성에 액세스하기 위해 모듈 개체를 가져올 필요가 없습니다.
Oliver Bestwalter

1

답변이 늦을 수도 있지만 정답을 찾지 못했습니다. inspect.stack()파이썬에서 가장 가깝고 정확한 솔루션 (보다 빠름 ) 3.7.x:

  # search for first module in the stack
  stack_frame = inspect.currentframe()
  while stack_frame:
    print('***', stack_frame.f_code.co_name, stack_frame.f_code.co_filename, stack_frame.f_lineno)
    if stack_frame.f_code.co_name == '<module>':
      if stack_frame.f_code.co_filename != '<stdin>':
        caller_module = inspect.getmodule(stack_frame)
      else:
        # piped or interactive import
        caller_module = sys.modules['__main__']
      if not caller_module is None:
        #... do something here ...
      break
    stack_frame = stack_frame.f_back

장점 :

  • globals()방법 보다 정확합니다 .
  • 예를 들어 후킹 또는 pytest다음 과 같은 3dparty 도구를 통해 추가 할 수있는 스택 중간 프레임에 의존하지 않습니다 .
*** foo ... ..
*** boo ... ..
*** runtest c:\python\x86\37\lib\site-packages\xonsh\pytest_plugin.py 58
*** pytest_runtest_call c:\python\x86\37\lib\site-packages\_pytest\runner.py 125
*** _multicall c:\python\x86\37\lib\site-packages\pluggy\callers.py 187
*** <lambda> c:\python\x86\37\lib\site-packages\pluggy\manager.py 86
*** _hookexec c:\python\x86\37\lib\site-packages\pluggy\manager.py 92
*** __call__ c:\python\x86\37\lib\site-packages\pluggy\hooks.py 286
*** <lambda> c:\python\x86\37\lib\site-packages\_pytest\runner.py 201
*** from_call c:\python\x86\37\lib\site-packages\_pytest\runner.py 229
*** call_runtest_hook c:\python\x86\37\lib\site-packages\_pytest\runner.py 201
*** call_and_report c:\python\x86\37\lib\site-packages\_pytest\runner.py 176
*** runtestprotocol c:\python\x86\37\lib\site-packages\_pytest\runner.py 95
*** pytest_runtest_protocol c:\python\x86\37\lib\site-packages\_pytest\runner.py 80
*** _multicall c:\python\x86\37\lib\site-packages\pluggy\callers.py 187
*** <lambda> c:\python\x86\37\lib\site-packages\pluggy\manager.py 86
*** _hookexec c:\python\x86\37\lib\site-packages\pluggy\manager.py 92
*** __call__ c:\python\x86\37\lib\site-packages\pluggy\hooks.py 286
*** pytest_runtestloop c:\python\x86\37\lib\site-packages\_pytest\main.py 258
*** _multicall c:\python\x86\37\lib\site-packages\pluggy\callers.py 187
*** <lambda> c:\python\x86\37\lib\site-packages\pluggy\manager.py 86
*** _hookexec c:\python\x86\37\lib\site-packages\pluggy\manager.py 92
*** __call__ c:\python\x86\37\lib\site-packages\pluggy\hooks.py 286
*** _main c:\python\x86\37\lib\site-packages\_pytest\main.py 237
*** wrap_session c:\python\x86\37\lib\site-packages\_pytest\main.py 193
*** pytest_cmdline_main c:\python\x86\37\lib\site-packages\_pytest\main.py 230
*** _multicall c:\python\x86\37\lib\site-packages\pluggy\callers.py 187
*** <lambda> c:\python\x86\37\lib\site-packages\pluggy\manager.py 86
*** _hookexec c:\python\x86\37\lib\site-packages\pluggy\manager.py 92
*** __call__ c:\python\x86\37\lib\site-packages\pluggy\hooks.py 286
*** main c:\python\x86\37\lib\site-packages\_pytest\config\__init__.py 90
*** <module> c:\Python\x86\37\Scripts\pytest.exe\__main__.py 7
  • Python 파이프 또는 대화 형 세션을 처리 할 수 ​​있습니다.

단점 :

  • 매우 정확하고 원하는 것과 같은 실행 파일에 등록 된 모듈을 반환 할 수 있습니다 pytest.exe.
  • inspect.getmodule 후크에 따라 유효한 모듈에서 여전히 None을 반환 할 수 있습니다.

파이썬에 대한 확장이 있습니다 : 전체 경로가 지정된 모듈을 가져 오는 방법?

이 경우 래퍼 기능을 가진 확장 :

def tkl_get_stack_frame_module_by_offset(skip_stack_frames = 0, use_last_frame_on_out_of_stack = False):
  ...

def tkl_get_stack_frame_module_by_name(name = '<module>'):
  ...

확장을 제대로 초기화하면됩니다.

# portable import to the global space
sys.path.append(<path-to-tacklelib-module-directory>)
import tacklelib as tkl

tkl.tkl_init(tkl, global_config = {'log_import_module':os.environ.get('TACKLELIB_LOG_IMPORT_MODULE')})

# cleanup
del tkl # must be instead of `tkl = None`, otherwise the variable would be still persist
sys.path.pop()

# use `tkl_*` functions directly from here ...
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.