Python 시간 측정 기능


122

각 함수에 소요 된 시간을 테스트하고 시간과 함께 이름을 인쇄하는 파이썬 함수를 만들고 싶습니다. 함수 이름을 인쇄하는 방법과 다른 방법이 있으면 알려주십시오.

def measureTime(a):
    start = time.clock() 
    a()
    elapsed = time.clock()
    elapsed = elapsed - start
    print "Time spent in (function name) is: ", elapsed

Python 프로파일 링 도구는 함수 이름과 각각에 소요 된 시간을 보여줄 수 있습니다. 여기에서 읽기 : docs.python.org/library/profile.html
Roadmaster

timeit측정을 위해 더 잘 사용 하십시오. 완벽하지는 않지만 찌르는 것을 훨씬 능가하며 timeit더 나은 것을 직접 만드는 것보다 사용하기가 훨씬 쉽습니다 .

답변:


241

우선, 프로파일 러를 사용하거나 적어도 timeit을 사용하는 것이 좋습니다 .

그러나 엄격하게 배우기 위해 자신의 타이밍 방법을 작성하고 싶다면 여기에 데코레이터를 사용하기 시작할 수 있습니다.

파이썬 2 :

def timing(f):
    def wrap(*args):
        time1 = time.time()
        ret = f(*args)
        time2 = time.time()
        print '%s function took %0.3f ms' % (f.func_name, (time2-time1)*1000.0)
        return ret
    return wrap

사용법은 매우 간단합니다. @timing 데코레이터를 사용하면됩니다.

@timing
def do_work():
  #code

파이썬 3 :

def timing(f):
    def wrap(*args, **kwargs):
        time1 = time.time()
        ret = f(*args, **kwargs)
        time2 = time.time()
        print('{:s} function took {:.3f} ms'.format(f.__name__, (time2-time1)*1000.0))

        return ret
    return wrap

참고 f.func_name함수 이름을 문자열 (Python 2) 또는 f.__name__ Python 3 으로 가져 오기 위해 호출 하고 있습니다.


4
내가 :) 싶어 ...하지만 너희들은 파이썬 프로파일 사용하는 저를 설득 정확히
Wazery

3
이것은 time.time ()이 epoch 이후 시간을 마이크로 초 단위로보고한다고 가정 한 것 같습니다. 문서에는 docs.python.org/2/library/time.html#time.time 초 단위로 시간이보고됩니다 .
Rahul Jha 2014

func에서 yield를 사용한 후에는 효과가 없습니다. 이 방법을 계속 사용하고 yield를 사용할 수있는 방법은 무엇입니까?
jiamo

def timing (f) : def wrap (* args, ** kwargs) : time1 = time.time () ret = f (* args, ** kwargs) time2 = time.time () print '% s 함수가 % 0.3을 사용했습니다. F MS '% (f.func_name (TIME2-TIME1) * 1000) 반환 RET 복귀 랩
비벡 Bagaria

1
직접 작성하는 단점은 무엇입니까? 경과 시간 목록을 저장하고 배포를 검토하는 것이 충분히 간단하지 않습니까?
3pitt

51

timeit모듈을 가지고 놀았을 때 인터페이스가 마음에 들지 않아 다음 두 방법에 비해 그다지 우아하지 않습니다.

다음 코드는 Python 3에 있습니다.

데코레이터 방법

이것은 @Mike의 방법과 거의 동일합니다. 여기에 추가 kwargs하고 functools포장하여 더 좋습니다.

def timeit(func):
    @functools.wraps(func)
    def newfunc(*args, **kwargs):
        startTime = time.time()
        func(*args, **kwargs)
        elapsedTime = time.time() - startTime
        print('function [{}] finished in {} ms'.format(
            func.__name__, int(elapsedTime * 1000)))
    return newfunc

@timeit
def foobar():
    mike = Person()
    mike.think(30)

컨텍스트 관리자 방법

from contextlib import contextmanager

@contextmanager
def timeit_context(name):
    startTime = time.time()
    yield
    elapsedTime = time.time() - startTime
    print('[{}] finished in {} ms'.format(name, int(elapsedTime * 1000)))

예를 들어 다음과 같이 사용할 수 있습니다.

with timeit_context('My profiling code'):
    mike = Person()
    mike.think()

그리고 with블록 내의 코드 는 시간이 정해집니다.

결론

첫 번째 방법을 사용하면 데코레이터를 쉽게 주석 처리하여 일반 코드를 얻을 수 있습니다. 그러나 그것은 함수의 시간을 측정 할 수만 있습니다. 코드의 일부가 함수로 만들지 않는 부분이 있다면 두 번째 방법을 선택할 수 있습니다.

예를 들어, 이제

images = get_images()
bigImage = ImagePacker.pack(images, width=4096)
drawer.draw(bigImage)

이제 시간을 정하고 싶습니다 bigImage = .... 함수로 변경하면 다음과 같습니다.

images = get_images()
bitImage = None
@timeit
def foobar():
    nonlocal bigImage
    bigImage = ImagePacker.pack(images, width=4096)
drawer.draw(bigImage)

그다지 좋지 않은 것 같습니다 ... nonlocal키워드 가없는 Python 2를 사용한다면 어떨까요?

대신 두 번째 방법을 사용하는 것이 여기에 매우 적합합니다.

images = get_images()
with timeit_context('foobar'):
    bigImage = ImagePacker.pack(images, width=4096)
drawer.draw(bigImage)

흥미로운 공헌이지만 언급 한 데코레이터 메소드에서 timeit인터페이스 를 변경 wraps()하고 functools모듈 의 기능을 사용해야 한다는 것은 쓸모가 없습니다 . 모든 추가 코드가 필요하지 않다는 것을 의미합니다.
Billal Begueradj

1
Needsimport functools
Guillaume Chevalier

1
주 당신의 장식은 원래 함수의 반환 값 푼다 것을
마크 반 Daele

11

timeit모듈 의 문제가 무엇인지 모르겠습니다 . 이것은 아마도 가장 간단한 방법 일 것입니다.

import timeit
timeit.timeit(a, number=1)

함수에 인수를 보내는 것도 가능합니다. 데코레이터를 사용하여 함수를 마무리하기 만하면됩니다. 자세한 설명 : http://www.pythoncentral.io/time-a-python-function/

고유 한 타이밍 문을 작성하는 데 관심이있는 유일한 경우는 함수를 한 번만 실행하고 반환 값을 얻으려는 경우입니다.

timeit모듈 사용의 장점 은 실행 횟수 를 반복 할 수 있다는 것 입니다. 다른 프로세스가 타이밍 정확도를 방해 할 수 있기 때문에 이것이 필요할 수 있습니다. 따라서 여러 번 실행하고 가장 낮은 값을 확인해야합니다.


3
래퍼와 데코레이터를 사용하여 함수에 인수를 전송합니까? 왜 안돼 timeit.timeit(lambda: func(a,b,c), number=1)? 터미널에서 가상 솔루션을 테스트 할 때 이것을 사용합니다.
Jack

11

Timeit에는 두 가지 큰 결함이 있습니다. 함수의 반환 값을 반환하지 않고 가져 오기를위한 추가 설정 코드를 전달해야하는 eval을 사용합니다. 이것은 두 문제를 간단하고 우아하게 해결합니다.

def timed(f):
  start = time.time()
  ret = f()
  elapsed = time.time() - start
  return ret, elapsed

timed(lambda: database.foo.execute('select count(*) from source.apachelog'))
(<sqlalchemy.engine.result.ResultProxy object at 0x7fd6c20fc690>, 4.07547402381897)

감사! 모든 Spark 종속성을 가져와야하므로 Apache Spark와 잘 작동하지 않습니다. 누가 그렇게 큰 오래된 문자열을 만들고 싶습니까? 이 솔루션은 훨씬 간단하고 유연합니다.
Paul

4

타이밍을위한 쉬운 도구가 있습니다. https://github.com/RalphMao/PyTimer

데코레이터 처럼 작동 할 수 있습니다 .

from pytimer import Timer
@Timer(average=False)      
def matmul(a,b, times=100):
    for i in range(times):
        np.dot(a,b)        

산출:

matmul:0.368434
matmul:2.839355

또한 네임 스페이스 컨트롤이 있는 플러그인 타이머 처럼 작동 할 수 있습니다 (많은 코드가 있고 다른 곳에서 호출 될 수있는 함수에 삽입하는 경우 유용합니다).

timer = Timer()                                           
def any_function():                                       
    timer.start()                                         

    for i in range(10):                                   

        timer.reset()                                     
        np.dot(np.ones((100,1000)), np.zeros((1000,500)))
        timer.checkpoint('block1')                        

        np.dot(np.ones((100,1000)), np.zeros((1000,500)))
        np.dot(np.ones((100,1000)), np.zeros((1000,500)))
        timer.checkpoint('block2')                        
        np.dot(np.ones((100,1000)), np.zeros((1000,1000)))

    for j in range(20):                                   
        np.dot(np.ones((100,1000)), np.zeros((1000,500)))
    timer.summary()                                       

for i in range(2):                                        
    any_function()                                        

산출:

========Timing Summary of Default Timer========
block2:0.065062
block1:0.032529
========Timing Summary of Default Timer========
block2:0.065838
block1:0.032891

도움이되기를 바랍니다.


3

데코레이터 Python 라이브러리를 사용하는 데코레이터 방법 :

import decorator

@decorator
def timing(func, *args, **kwargs):
    '''Function timing wrapper
        Example of using:
        ``@timing()``
    '''

    fn = '%s.%s' % (func.__module__, func.__name__)

    timer = Timer()
    with timer:
        ret = func(*args, **kwargs)

    log.info(u'%s - %0.3f sec' % (fn, timer.duration_in_seconds()))
    return ret

내 블로그에서 게시물보기 :

mobilepro.pl 블로그에 게시

Google Plus의 내 게시물


1

내 방식 :

from time import time

def printTime(start):
    end = time()
    duration = end - start
    if duration < 60:
        return "used: " + str(round(duration, 2)) + "s."
    else:
        mins = int(duration / 60)
        secs = round(duration % 60, 2)
        if mins < 60:
            return "used: " + str(mins) + "m " + str(secs) + "s."
        else:
            hours = int(duration / 3600)
            mins = mins % 60
            return "used: " + str(hours) + "h " + str(mins) + "m " + str(secs) + "s."

start = time()함수 / 루프를 실행하기 전과 printTime(start)블록 바로 뒤에 변수를 설정합니다 .

그리고 당신은 답을 얻었습니다.

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