언어/Python

[ Python ] Decorator와 Profiler 사용하기

Soso Dev 2024. 7. 7. 19:04
반응형

파이썬에서 데코레이터(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를 사용하여 더 정교한 프로파일링을 수행할 수 있습니다. 데코레이터는 함수에 추가 기능을 쉽게 추가할 수 있는 강력한 도구로, 함수의 성능을 모니터링하고 최적화하는 데 매우 유용합니다.

반응형