Python:inspect
inspect 모듈은 모듈, 클래스, 메서드, 함수, 트레이스백, 프레임 객체 및 코드 객체와 같은 라이브 객체에 대한 정보를 얻는 데 도움이 되는 몇 가지 유용한 함수를 제공합니다. 예를 들어, 클래스의 내용을 검사하거나, 메서드의 소스 코드를 꺼내오거나, 함수의 인자 리스트를 추출하고 포맷하거나, 자세한 트레이스백을 표시하는 데 필요한 모든 정보를 얻는 데 도움이 될 수 있습니다.
이 모듈은 4가지 종류의 주요 서비스를 제공합니다
- 형 검사
- 소스 코드 가져오기
- 클래스와 함수 검사
- 인터프리터 스택 검사
형과 멤버
getmembers() 함수는 클래스나 모듈과 같은 객체의 멤버를 검색합니다. 이름이 is
로 시작하는 함수는 주로 getmembers()의 두 번째 인자로 쓰기에 편리하도록 제공됩니다. 또한 다음과 같은 특수 어트리뷰트를 언제 찾을 수 있는지 결정하는 데 도움이 됩니다:
형 | 어트리뷰트 | 설명 |
모듈 | doc | 도큐멘테이션 문자열 |
file | 파일명 (내장 모듈에는 없습니다) | |
클래스 | doc | 도큐멘테이션 문자열 |
name | 이 클래스가 정의된 이름 | |
qualname | 정규화된 이름 | |
module | 이 클래스가 정의된 모듈의 이름 | |
메서드 | doc | 도큐멘테이션 문자열 |
name | 이 메서드가 정의된 이름 | |
qualname | 정규화된 이름 | |
func | 메서드의 구현을 포함하는 함수 객체 | |
self | 이 메서드가 연결된 인스턴스, 또는 None | |
module | 이 메서드가 정의된 모듈의 이름 | |
함수 | doc | 도큐멘테이션 문자열 |
name | 이 함수가 정의된 이름 | |
qualname | 정규화된 이름 | |
code | 컴파일된 함수 바이트 코드를 포함하는 코드 객체 | |
defaults | 위치나 키워드 매개 변수에 대한 기본값의 튜플 | |
kwdefaults | 키워드 전용 매개 변수의 기본값 매핑 | |
globals | 이 함수가 정의된 전역 이름 공간 | |
annotations | 매개 변수 이름에서 어노테이션으로의 매핑; | |
module | 이 함수가 정의된 모듈의 이름 | |
트레이스백 | tb_frame | 이 수준의 프레임 객체 |
tb_lasti | 바이트 코드에서 마지막으로 시도한 명령의 인덱스 | |
tb_lineno | 파이썬 소스 코드의 현재 줄 번호 | |
tb_next | (이 수준에서 호출된) 다음 내부(inner) 트레이스백 객체 | |
프레임 | f_back | 다음 외부(outer) 프레임 객체 (이 프레임의 호출자) |
f_builtins | 이 프레임이 보는 내장 이름 공간 | |
f_code | 이 프레임에서 실행되는 코드 객체 | |
f_globals | 이 프레임이 보는 전역 이름 공간 | |
f_lasti | 바이트 코드에서 마지막으로 시도한 명령의 인덱스 | |
f_lineno | 파이썬 소스 코드의 현재 줄 번호 | |
f_locals | 이 프레임이 보는 지역 이름 공간 | |
f_trace | 이 프레임의 추적 함수(tracing function), 또는 None | |
코드 | co_argcount | 인자 개수 (키워드 전용 인자, * 또는 ** 인자는 포함하지 않습니다) |
co_code | 컴파일된 날 바이트 코드의 문자열 | |
co_cellvars | (포함하는 스코프가 참조하는) 셀 변수 이름의 튜플 | |
co_consts | 바이트 코드에서 사용되는 상수의 튜플 | |
co_filename | 이 코드 객체가 만들어진 파일의 이름 | |
co_firstlineno | 파이썬 소스 코드의 첫 줄 번호 | |
co_flags | CO_* 플래그의 비트맵, 여기를 더 읽어보십시오 | |
co_lnotab | 줄 번호에서 바이트 코드 인덱스로의 인코딩된 매핑 | |
co_freevars | (함수의 클로저를 통해 참조되는) 자유 변수(free variables) 이름의 튜플 | |
co_posonlyargcount | 위치 전용 인자의 개수 | |
co_kwonlyargcount | 키워드 전용 인자의 개수 (** 인자는 제외합니다) | |
co_name | 이 코드 객체가 정의된 이름 | |
co_names | 지역 변수 이름의 튜플 | |
co_nlocals | 지역 변수의 개수 | |
co_stacksize | 필요한 가상 기계 스택 공간 | |
co_varnames | 인자와 지역 변수 이름의 튜플 | |
제너레이터 | name | 이름 |
qualname | 정규화된 이름 | |
gi_frame | 프레임 | |
gi_running | 제너레이터가 실행 중입니까? | |
gi_code | 코드 | |
gi_yieldfrom | | |
코루틴 | name | 이름 |
qualname | 정규화된 이름 | |
cr_await | 어웨이트 중인 객체, 또는 | |
cr_frame | 프레임 | |
cr_running | 코루틴이 실행 중입니까? | |
cr_code | 코드 | |
cr_origin | 코루틴이 생성된 곳, 또는 | |
내장 | doc | 도큐멘테이션 문자열 |
name | 이 함수나 메서드의 원래 이름 | |
qualname | 정규화된 이름 | |
self | 메서드가 연결된 인스턴스, 또는 |
getmembers
getdoc
문서 코맨트 문자열을 획득한다. 주로 __doc__
같은 속성을 사용.
Get docstring of class attribute
클래스의 Attribute 에 추가한 docstring 주석을 획득하고 싶을 때 Python:ast#Get docstring of class attribute 항목을 참조.
getfullargspec
다음과 같이 출력 된다.
Python 3.3 부터 #signature 사용 가능.
signature
Signature 객체는 호출 가능 객체의 호출 서명과 해당 반환 주석을 나타냅니다. Signature 객체를 검색하려면 signature()
함수를 사용하십시오.
Example:
from inspect import signature
def foo(a, *, b:int, **kwargs):
pass
sig = signature(foo)
str(sig)
str(sig.parameters['b'])
sig.parameters['b'].annotation
Signature class
Signature 객체는 함수의 호출 서명과 해당 반환 주석을 나타냅니다. 함수가 허용하는 각 매개변수에 대해 매개변수 컬렉션에 Parameter 개체를 저장합니다.
replace
객체에 저장된 서명을 변경할 수 있다. (원본 심볼의 서명을 바꾸는게 아니다)
bind(args, *kwargs)
위치와 키워드 인자에서 매개 변수로의 매핑을 만듭니다. args와 *kwargs가 서명과 일치하면 #BoundArguments를 반환하고, 그렇지 않으면 TypeError를 발생시킵니다.
이 함수를 사용하여 필요한 인자 전달을 동적으로 조정할 수 있다.
def foo(a, b='ham', *args):
pass
sig = inspect.signature(foo)
ba = sig.bind('spam')
ba.apply_defaults()
print(ba.arguments)
foo(*ba.args, **ba.kwargs)
BoundArguments
Signature.bind()
나 Signature.bind_partial()
호출의 결과. 인자에서 함수의 매개 변수로의 매핑을 보관합니다.
apply_defaults
빈 아규먼트중 기본값이 있을 경우 그 값으로 채운다.
def foo(a, b='ham', *args):
pass
ba = inspect.signature(foo).bind('spam')
ba.apply_defaults()
print(ba.arguments)
Code information
init 함수 검사
class Super:
def __init__(self, name, kwarg='default'):
print('instantiated')
self.name = name
>>> import inspect
>>> inspect.signature(Super.__init__)
<Signature (self, name, kwarg='default')>
현재 파일에서 특정 클래스를 상속받은 모든 클래스 검색
# -*- coding: utf-8 -*-
from typing import Type, Dict
from recc.exception.base_exception import ReccBaseException
CODE_RECC_OK = 0
CODE_RECC_ERROR = 10
class ReccOk(ReccBaseException):
def __init__(self, *args, code=CODE_RECC_OK):
super().__init__(*args, code=code)
assert self.is_recc_code()
class ReccError(ReccBaseException):
def __init__(self, *args, code=CODE_RECC_ERROR):
super().__init__(*args, code=code)
assert self.is_recc_code()
def get_recc_code_to_error_type_map() -> Dict[int, Type[ReccBaseException]]:
from inspect import getmembers, isclass
from sys import modules
def _is_recc_error_type(x) -> bool:
return isclass(x) and issubclass(x, ReccBaseException)
result = dict()
class_members = getmembers(modules[__name__], _is_recc_error_type)
for member in class_members:
class_name = member[0]
class_type = member[1]
assert isinstance(class_name, str)
assert isinstance(class_type, type)
assert issubclass(class_type, ReccBaseException)
instance: ReccBaseException = class_type()
assert instance.is_unknown_code() or instance.is_recc_code()
result[instance.code] = class_type
return result
RECC_CODE_TO_ERROR_TYPE_MAP = get_recc_code_to_error_type_map()
함수 호출시 전달된 변수의 변수명을 알아해는 방법
WARNING |
사용을 권장하지 않는다. |
import inspect
def foo(a, f, b):
frame = inspect.currentframe()
frame = inspect.getouterframes(frame)[1]
string = inspect.getframeinfo(frame[0]).code_context[0].strip()
args = string[string.find('(') + 1:-1].split(',')
names = []
for i in args:
if i.find('=') != -1:
names.append(i.split('=')[1].strip())
else:
names.append(i)
print names
def main():
e = 1
c = 2
foo(e, 1000, b = c)
main()
Output: