2016-08-27 2 views
1

로깅의 경우 각 함수가 함수의 시작과 끝에서 고유 한 이름을 기록하도록하고 싶습니다.파이썬에서는 함수를 장식하여 시작과 끝을 기록 할 수 있습니까?

def my_function(): 
    print("Enter my_function") 
    # ... 
    print("Leave my_function") 

기능의 이름을 변경하면 이러한 인쇄 메시지도 함께 업데이트해야합니다. 나는 이것을 자동화하는 방법을 찾고있다.

def my_decorator(func): 
    print("Enter ", func.__name__) 
    func() 
    print("Leave ", func.__name__) 

def my_function(): 
    # do the work 
    pass 

# main: 
my_decorator(my_function) 

이 어쩌면 장식을 사용하여 간단한 방법으로 할 수 있습니까? my_function에 매개 변수가 있으면 어떻게 보이나요?

+2

내가 이해하지 못하는 것은 정확히이 작업을 수행하는 방법을 설명 장식에 자습서 중 하나를 찾지 못했습니다 방법이다. 데코레이터의 표준 예제입니다. –

+0

Python의 문맥 관리자 (문장 포함)를 읽고 싶을 수도 있습니다 : 그것이 그곳에있는 이유입니다. https://jeffknupp.com/blog/2016/03/07/python-with-context-managers/ – boardrider

답변

6

당신은 맞습니다. 데코레이터를 사용하면 이러한 동작을 구현하는 완벽한 방법입니다.

알아 두어야 할 것은 장식 자의 작동 방식입니다. 단순히 함수를 인수로 사용하고 다른 함수를 반환합니다. 이 리턴 된 다른 함수는 인수 함수를 랩 (wrap)하기위한 것입니다.

def log_in_out(func): 

    def decorated_func(*args, **kwargs): 
     print("Enter ", func.__name__) 
     result = func(*args, **kwargs) 
     print("Leave ", func.__name__) 
     return result 

    return decorated_func 

@log_in_out 
def my_function(): 
    print("Inside my_function") 
    return 42 


val = my_function() 

print(val) 

# Output: 
# Enter my_function 
# Inside my_function 
# Leave my_function 
# 42 

또한 @ ŁukaszRogalski functools.wraps 사용의 응답 함수의 참조 문을 보존 유용되어 있습니다. 내가 제어 흐름이해야한다고 생각하기 때문에 내가

def log_in_out(func): 

    def decorated_func(*args, **kwargs): 
     name = func.__name__ 
     print("Enter", name) 
     try: 
      result = func(*args, **kwargs) 
      print("Leave", name) 
     except: 
      print("Error in", name) 
      raise 
     return result 

    return decorated_func 

참고 오류를 다시는-던져 : 마지막으로

, @MartinBonner에서 좋은 생각, 당신은 또한 당신의 함수에서 오류를 기록하는 데 사용할 수 있다는 것입니다 기능의 외부에서 관리해야합니다.

고급 로깅의 경우 많은 기능을 제공하는 the built-in module을 사용해야합니다.

+0

케이크 장식의 경우 래핑 된 함수가 예외를 throw하는 경우 지원을 추가 할 수 있습니다. –

+0

@MartinBonner 좋은 점, 감사합니다, 답변에 추가되었습니다. – Delgan

1

물론, 스타 args와 스타 kwargs로 정말 간단합니다. functools.wraps은 입력 기능에서 래퍼로 메타 데이터 (__name__, __doc__ 등)를 다시 쓰는 데 사용됩니다. 함수 객체 문자열 표현이 너 너무 길면 print("Enter", f.__name__)을 대신 사용할 수 있습니다.

import functools 


def d(f): 
    @functools.wraps(f) 
    def wrapper(*args, **kwargs): 
     print("Enter", f) 
     result = f(*args, **kwargs) 
     print("Exit", f) 
     return result 
    return wrapper 


@d 
def my_func(): 
    print("hello") 


@d 
def my_func2(x): 
    print(x) 


my_func() 
my_func2("world") 

출력 :

Enter <function my_func at 0x10ca93158> 
hello 
Exit <function my_func at 0x10ca93158> 
Enter <function my_func2 at 0x10caed950> 
world 
Exit <function my_func2 at 0x10caed950> 
관련 문제