본문 바로가기

언어/Python

[ Python ] Decorator와 Fuction Profiler 사용하기

반응형

파이썬에서 데코레이터(Decorator)와 함수 프로파일러(Function Profiler)를 사용하는 방법을 설명하겠습니다. 데코레이터는 함수를 감싸서 추가 기능을 제공하는 강력한 도구입니다. 함수 프로파일러는 함수의 성능을 측정하는 도구로, 주로 함수의 실행 시간을 측정하는 데 사용됩니다. 데코레이터를 사용하여 프로파일러를 구현하는 방법을 소개하겠습니다.

1. 데코레이터 기본 개념

데코레이터는 다른 함수를 인수로 받아 새로운 함수를 반환하는 함수입니다. 이로써 원래 함수에 추가적인 기능을 덧붙일 수 있습니다.

기본 데코레이터 예제

def my_decorator(func):
    def wrapper(*args, **kwargs):
        print("Something is happening before the function is called.")
        result = func(*args, **kwargs)
        print("Something is happening after the function is called.")
        return result
    return wrapper

@my_decorator
def say_hello():
    print("Hello!")

say_hello()

출력:

Something is happening before the function is called.
Hello!
Something is happening after the function is called.

2. 함수 프로파일러 데코레이터

함수의 실행 시간을 측정하는 데코레이터를 작성할 수 있습니다.

실행 시간 측정 데코레이터

import time

def profiler(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"{func.__name__} 실행 시간: {end_time - start_time:.4f}초")
        return result
    return wrapper

@profiler
def slow_function():
    time.sleep(2)
    print("Function finished")

slow_function()

출력:

Function finished
slow_function 실행 시간: 2.0003초

3. 프로파일러 데코레이터 확장

여러 함수의 실행 시간을 측정하고 결과를 정리하기 위해 더 확장된 프로파일러 데코레이터를 작성할 수 있습니다.

import time
from functools import wraps

def profiler(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        wrapper.total_time += (end_time - start_time)
        wrapper.call_count += 1
        print(f"{func.__name__} 실행 시간: {end_time - start_time:.4f}초")
        return result
    wrapper.total_time = 0
    wrapper.call_count = 0
    return wrapper

@profiler
def fast_function():
    time.sleep(1)
    print("Fast function finished")

@profiler
def slow_function():
    time.sleep(2)
    print("Slow function finished")

fast_function()
slow_function()
fast_function()
slow_function()

print(f"fast_function 총 실행 시간: {fast_function.total_time:.4f}초, 호출 횟수: {fast_function.call_count}")
print(f"slow_function 총 실행 시간: {slow_function.total_time:.4f}초, 호출 횟수: {slow_function.call_count}")

출력:

Fast function finished
fast_function 실행 시간: 1.0002초
Slow function finished
slow_function 실행 시간: 2.0004초
Fast function finished
fast_function 실행 시간: 1.0001초
Slow function finished
slow_function 실행 시간: 2.0003초
fast_function 총 실행 시간: 2.0003초, 호출 횟수: 2
slow_function 총 실행 시간: 4.0007초, 호출 횟수: 2

4. 고급 프로파일링: cProfilepstats 사용

파이썬 표준 라이브러리에는 고급 프로파일링 도구인 cProfile과 결과를 분석할 수 있는 pstats 모듈이 포함되어 있습니다.

cProfile 사용 예제

import cProfile

def fast_function():
    time.sleep(1)
    print("Fast function finished")

def slow_function():
    time.sleep(2)
    print("Slow function finished")

def main():
    fast_function()
    slow_function()

cProfile.run('main()')

출력:

         3 function calls in 3.000 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    1.000    1.000    1.000    1.000 <ipython-input-6-7c71e2b8e208>:3(fast_function)
        1    2.000    2.000    2.000    2.000 <ipython-input-6-7c71e2b8e208>:7(slow_function)
        1    0.000    0.000    3.000    3.000 <ipython-input-6-7c71e2b8e208>:11(main)
        1    0.000    0.000    3.000    3.000 {built-in method builtins.exec}
        1    0.000    0.000    0.000    0.000 {built-in method time.sleep}

pstats로 결과 분석

프로파일링 결과를 파일에 저장하고 pstats로 분석할 수 있습니다.

import cProfile
import pstats

def main():
    fast_function()
    slow_function()

# 프로파일링 결과를 파일에 저장
cProfile.run('main()', 'profile_output')

# 저장된 결과 분석
p = pstats.Stats('profile_output')
p.strip_dirs().sort_stats('cumulative').print_stats(10)

이러한 방법들을 통해 파이썬에서 데코레이터를 사용하여 함수의 실행 시간을 측정하고, cProfilepstats를 사용하여 더 정교한 프로파일링을 수행할 수 있습니다. 데코레이터는 함수에 추가 기능을 쉽게 추가할 수 있는 강력한 도구로, 함수의 성능을 모니터링하고 최적화하는 데 매우 유용합니다.

반응형