Development Tip

Python에서 경과 된 시간 측정

yourdevel 2020. 9. 27. 14:09
반응형

Python에서 경과 된 시간 측정


내가 원하는 것은 내 코드의 어딘가에서 시간을 계산 한 다음 전달 된 시간을 가져와 몇 가지 기능을 실행하는 데 걸린 시간을 측정하는 것입니다. timeit 모듈을 잘못 사용하고 있다고 생각하지만 문서가 혼란 스럽습니다.

import timeit

start = timeit.timeit()
print("hello")
end = timeit.timeit()
print(end - start)

두 지점 사이의 경과 벽시계 시간을 측정하려면 다음을 사용할 수 있습니다 time.time().

import time

start = time.time()
print("hello")
end = time.time()
print(end - start)

이것은 실행 시간을 초 단위로 제공합니다.

3.3 이후 또 다른 옵션은 사용할 수 있습니다 perf_counter또는 process_time귀하의 요구 사항에 따라. 3.3 이전에는 사용하는 것이 좋습니다 time.clock( Amber 에게 감사 ). 그러나 현재 사용되지 않습니다.

Unix에서는 현재 프로세서 시간을 초 단위의 부동 소수점 숫자로 반환합니다. 정밀도와 실제로 "프로세서 시간"의 의미에 대한 정의는 동일한 이름의 C 함수에 따라 달라집니다.

Windows에서이 함수는 Win32 함수를 기반으로이 함수에 대한 첫 번째 호출 이후 경과 된 벽시계 초를 부동 소수점 숫자로 반환합니다 QueryPerformanceCounter(). 해상도는 일반적으로 1 마이크로 초보다 좋습니다.

버전 3.3부터 사용되지 않습니다 :이 함수의 동작은 플랫폼에 따라 다릅니다 : 사용 perf_counter()또는 process_time()대신 , 사용자의 요구 사항에 따라 잘 정의 된 동작을 할 수 있습니다.


사용 timeit.default_timer대신에 timeit.timeit. 전자는 플랫폼과 Python 버전에서 사용할 수있는 최고의 시계를 자동으로 제공합니다.

from timeit import default_timer as timer

start = timer()
# ...
end = timer()
print(end - start) # Time in seconds, e.g. 5.38091952400282

timeit.default_timer 는 OS에 따라 time.time () 또는 time.clock ()에 할당됩니다. Python 3.3 이상에서 default_timer모든 플랫폼에서 time.perf_counter () 입니다. 참조 파이썬 - time.clock () 대로 time.time () - 정도?

또한보십시오:


Python 3 만 해당 :

time.clock () 은 Python 3.3 에서 더 이상 사용되지 않으므로time.perf_counter() 시스템 전체 타이밍에 사용하거나 time.process_time()프로세스 전체 타이밍에 사용하는 방식대로 사용하고 싶을 것입니다 time.clock().

import time

t = time.process_time()
#do some stuff
elapsed_time = time.process_time() - t

새로운 기능 process_time은 수면 중 경과 된 시간을 포함하지 않습니다.


시간을 정하고 싶은 기능이 주어지면

test.py :

def foo(): 
    # print "hello"   
    return "hello"

사용하는 가장 쉬운 방법 timeit은 명령 줄에서 호출하는 것입니다.

% python -mtimeit -s'import test' 'test.foo()'
1000000 loops, best of 3: 0.254 usec per loop

time.time또는 time.clock(순진하게) 기능의 속도를 비교 하려고하지 마십시오 . 잘못된 결과를 제공 할 수 있습니다 .

추신. 시간을 정하려는 함수에 print 문을 넣지 마십시오. 그렇지 않으면 측정 된 시간 은 터미널속도에 따라 달라집니다 .


with블록 에 들어갈 때 시작 시간을 자동으로 기억 한 다음 블록 종료시 종료 시간을 고정 하는 컨텍스트 관리자를 사용하여이 작업을 수행하는 것은 재미 있습니다. 약간의 속임수를 사용하면 동일한 컨텍스트 관리자 기능에서 블록 내에서 실행중인 경과 시간 집계를 얻을 수도 있습니다.

코어 라이브러리에는이 기능이 없습니다 (하지만 그래야합니다). 일단 배치되면 다음과 같은 작업을 수행 할 수 있습니다.

with elapsed_timer() as elapsed:
    # some lengthy code
    print( "midpoint at %.2f seconds" % elapsed() )  # time so far
    # other lengthy code

print( "all done at %.2f seconds" % elapsed() )

트릭을 수행하기에 충분한 컨텍스트 관리자 코드는 다음과 같습니다 .

from contextlib import contextmanager
from timeit import default_timer

@contextmanager
def elapsed_timer():
    start = default_timer()
    elapser = lambda: default_timer() - start
    yield lambda: elapser()
    end = default_timer()
    elapser = lambda: end-start

실행 가능한 데모 코드 :

import time

with elapsed_timer() as elapsed:
    time.sleep(1)
    print(elapsed())
    time.sleep(2)
    print(elapsed())
    time.sleep(3)

이 함수의 설계에 따라의 반환 값은 elapsed()블록 종료시 고정되고 추가 호출은 동일한 기간 (이 장난감 예제에서는 약 6 초)을 반환합니다.


나는 이것을 선호한다. timeit문서는 너무 혼란 스럽습니다.

from datetime import datetime 

start_time = datetime.now() 

# INSERT YOUR CODE 

time_elapsed = datetime.now() - start_time 

print('Time elapsed (hh:mm:ss.ms) {}'.format(time_elapsed))

여기에는 어떤 형식도 지정되어 있지 않습니다. 그냥 hh:mm:ss출력물에 으므로time_elapsed


측정 시간 (초) :

from timeit import default_timer as timer
from datetime import timedelta

start = timer()
end = timer()
print(timedelta(seconds=end-start))

출력 :

0:00:01.946339

time.time실행을 측정하는 데 사용하면 컴퓨터의 다른 프로세스에서 소비 한 실행 시간을 포함하여 명령의 전체 실행 시간을 알 수 있습니다. 사용자가 알아 차리는 시간이지만 다른 코드 스 니펫 / 알고리즘 / 함수 / ...를 비교하고 싶다면 좋지 않습니다.

추가 정보 timeit:

프로파일 링에 대한 더 깊은 통찰력이 필요한 경우 :

업데이트 : 작년에 http://pythonhosted.org/line_profiler/ 를 많이 사용 했는데 매우 유용하다는 것을 알게되었고 Pythons 프로필 모듈 대신 사용하는 것이 좋습니다.


다음은 "hh : mm : ss"문자열을 반환하는 작은 타이머 클래스입니다.

class Timer:
  def __init__(self):
    self.start = time.time()

  def restart(self):
    self.start = time.time()

  def get_time_hhmmss(self):
    end = time.time()
    m, s = divmod(end - self.start, 60)
    h, m = divmod(m, 60)
    time_str = "%02d:%02d:%02d" % (h, m, s)
    return time_str

용법:

# Start timer
my_timer = Timer()

# ... do something

# Get time string:
time_hhmmss = my_timer.get_time_hhmmss()
print("Time elapsed: %s" % time_hhmmss )

# ... use the timer again
my_timer.restart()

# ... do something

# Get time:
time_hhmmss = my_timer.get_time_hhmmss()

# ... etc

python cProfile 및 pstats 모듈은 기존 함수 주변에 코드를 추가하지 않고도 특정 함수에서 경과 된 시간을 측정 할 수있는 훌륭한 지원을 제공합니다.

예를 들어 파이썬 스크립트 timeFunctions.py가있는 경우 :

import time

def hello():
    print "Hello :)"
    time.sleep(0.1)

def thankyou():
    print "Thank you!"
    time.sleep(0.05)

for idx in range(10):
    hello()

for idx in range(100):
    thankyou()

프로파일 러를 실행하고 파일에 대한 통계를 생성하려면 다음을 실행하면됩니다.

python -m cProfile -o timeStats.profile timeFunctions.py

이것이하는 일은 cProfile 모듈을 사용하여 timeFunctions.py의 모든 함수를 프로파일 링하고 timeStats.profile 파일에서 통계를 수집하는 것입니다. 기존 모듈 (timeFunctions.py)에 코드를 추가 할 필요가 없었으며 이는 모든 모듈에서 수행 할 수 있습니다.

stats 파일이 있으면 다음과 같이 pstats 모듈을 실행할 수 있습니다.

python -m pstats timeStats.profile

이것은 많은 멋진 기능을 제공하는 대화 형 통계 브라우저를 실행합니다. 특정 사용 사례의 경우 함수에 대한 통계 만 확인할 수 있습니다. 이 예제에서 두 함수의 통계를 확인하면 다음과 같은 결과를 볼 수 있습니다.

Welcome to the profile statistics browser.
timeStats.profile% stats hello
<timestamp>    timeStats.profile

         224 function calls in 6.014 seconds

   Random listing order was used
   List reduced from 6 to 1 due to restriction <'hello'>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
       10    0.000    0.000    1.001    0.100 timeFunctions.py:3(hello)

timeStats.profile% stats thankyou
<timestamp>    timeStats.profile

         224 function calls in 6.014 seconds

   Random listing order was used
   List reduced from 6 to 1 due to restriction <'thankyou'>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
      100    0.002    0.000    5.012    0.050 timeFunctions.py:7(thankyou)

더미 예제는 많은 일을하지 않지만 무엇을 할 수 있는지에 대한 아이디어를 제공합니다. 이 접근 방식의 가장 좋은 점은 이러한 숫자를 얻고 분명히 프로파일 링을 돕기 위해 기존 코드를 편집 할 필요가 없다는 것입니다.


타이밍 코드에 대한 또 다른 컨텍스트 관리자가 있습니다.

용법:

from benchmark import benchmark

with benchmark("Test 1+1"):
    1+1
=>
Test 1+1 : 1.41e-06 seconds

또는 시간 가치가 필요한 경우

with benchmark("Test 1+1") as b:
    1+1
print(b.time)
=>
Test 1+1 : 7.05e-07 seconds
7.05233786763e-07

bench.py :

from timeit import default_timer as timer

class benchmark(object):

    def __init__(self, msg, fmt="%0.3g"):
        self.msg = msg
        self.fmt = fmt

    def __enter__(self):
        self.start = timer()
        return self

    def __exit__(self, *args):
        t = timer() - self.start
        print(("%s : " + self.fmt + " seconds") % (self.msg, t))
        self.time = t

http://dabeaz.blogspot.fr/2010/02/context-manager-for-timing-benchmarks.html 에서 수정


프로파일 러 모듈을 사용하십시오. 매우 상세한 프로필을 제공합니다.

import profile
profile.run('main()')

다음과 같이 출력됩니다.

          5 function calls in 0.047 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    0.000    0.000 :0(exec)
        1    0.047    0.047    0.047    0.047 :0(setprofile)
        1    0.000    0.000    0.000    0.000 <string>:1(<module>)
        0    0.000             0.000          profile:0(profiler)
        1    0.000    0.000    0.047    0.047 profile:0(main())
        1    0.000    0.000    0.000    0.000 two_sum.py:2(twoSum)

나는 그것이 매우 유익하다는 것을 알았습니다.


여기에 많은 좋은 답변과 다른 몇 가지 기사를 살펴본 결과가 있습니다.

첫째, 항상 사용 timeit하고 싶지 않습니다 time.time(많은 경우 성능 카운터 API).

  1. timeit OS 및 Python 버전에서 사용 가능한 최고의 타이머를 선택합니다.
  2. timeit 가비지 수집을 비활성화하지만 이것은 당신이 원하거나 원하지 않을 수 있습니다.

이제 문제는 시간 설정이 필요하고 가져 오기가 많으면 상황이 좋지 않기 때문에 사용하기가 그렇게 간단하지 않다는 것입니다. 이상적으로는 데코레이터를 원하거나 with블록 및 측정 시간을 사용합니다. 안타깝게도이를 위해 사용할 수있는 내장 기능이 없으므로 작은 유틸리티 모듈 아래에 만들었습니다.

타이밍 유틸리티 모듈

# utils.py
from functools import wraps
import gc
import timeit

def MeasureTime(f):
    @wraps(f)
    def _wrapper(*args, **kwargs):
        gcold = gc.isenabled()
        gc.disable()
        start_time = timeit.default_timer()
        try:
            result = f(*args, **kwargs)
        finally:
            elapsed = timeit.default_timer() - start_time
            if gcold:
                gc.enable()
            print('Function "{}": {}s'.format(f.__name__, elapsed))
        return result
    return _wrapper

class MeasureBlockTime:
    def __init__(self,name="(block)", no_print = False, disable_gc = True):
        self.name = name
        self.no_print = no_print
        self.disable_gc = disable_gc
    def __enter__(self):
        if self.disable_gc:
            self.gcold = gc.isenabled()
            gc.disable()
        self.start_time = timeit.default_timer()
    def __exit__(self,ty,val,tb):
        self.elapsed = timeit.default_timer() - self.start_time
        if self.disable_gc and self.gcold:
            gc.enable()
        if not self.no_print:
            print('Function "{}": {}s'.format(self.name, self.elapsed))
        return False #re-raise any exceptions

시간 함수 방법

이제 데코레이터를 앞에 놓는 것만으로 모든 함수의 시간을 측정 할 수 있습니다.

import utils

@utils.MeasureTime
def MyBigFunc():
    #do something time consuming
    for i in range(10000):
        print(i)

타임 코드 블록 방법

코드의 시간 부분을 원한다면 with블록 안에 넣으십시오 .

import utils

#somewhere in my code

with utils.MeasureBlockTime("MyBlock"):
    #do something time consuming
    for i in range(10000):
        print(i)

# rest of my code

장점

몇 가지 반백 버전이 떠 다니므로 몇 가지 하이라이트를 지적하고 싶습니다.

  1. 앞에서 설명한 이유로 time.time 대신 timeit의 타이머를 사용하십시오.
  2. 타이밍 동안 GC를 비활성화합니다.
  3. 데코레이터는 명명되거나 명명되지 않은 매개 변수가있는 함수를 허용합니다.
  4. 블록 타이밍에서 인쇄를 비활성화하는 기능 ( with utils.MeasureBlockTime() as t사용 t.elapsed).
  5. 블록 타이밍을 위해 gc를 활성화 상태로 유지하는 기능.

(Ipython에서만) % timeit사용 하여 평균 처리 시간을 측정 할 수 있습니다 .

def foo():
    print "hello"

그리고:

%timeit foo()

결과는 다음과 같습니다.

10000 loops, best of 3: 27 µs per loop

이제 2019 년입니다. 간결한 방법으로 해봅시다.

from ttictoc import TicToc
t = TicToc() ## TicToc("name")
t.tic();
# your code ...
t.toc();
print(t.elapsed)

다른 접근 방식 대신이 접근 방식을 사용할 때의 이점 :

  1. 간결하고 간단합니다. 프로그래머가 다음과 같은 추가 변수를 작성하도록 요구하지 않습니다.
    t1 = time ()
    t2 = time ()
    elapsed = t2-t1
  2. 중첩 포함
t = TicToc(nested=True)
t.tic()
some code1...
t.tic()
some code2...
t.tic()
some code3...
print(t.toc()) # Prints time for code 3 
print(t.toc()) # Prints time for code 2 with code 3
print(t.toc()) # Prints time for code 1 with code 2 and 3
  1. 틱톡의 이름을 보존하십시오.
t = TicToc("save user")
print(t.name)

자세한 지침 은이 링크참조하십시오 .


python3에서 :

from time import sleep, perf_counter as pc
t0 = pc()
sleep(1)
print(pc()-t0)

우아하고 짧습니다.


나는 간단하다 (python 3) :

from timeit import timeit

timeit(lambda: print("hello"))

단일 실행에 대한 출력은 마이크로 초 입니다.

2.430883963010274

설명 : timeit은 기본적으로 익명 함수를 100 만 번 실행 하며 결과는 초 단위 로 제공됩니다 . 따라서 한 번의 단일 실행에 대한 결과 는 동일한 양이지만 평균 마이크로 초 입니다.


들어 느린 동작 낮은 추가 할 반복 또는 당신은 영원히 기다리고있을 수 있습니다 :

import time

timeit(lambda: time.sleep(1.5), number=1)

반복 횟수대한 출력은 항상 초 단위 입니다 .

1.5015795179999714

일종의 슈퍼 나중 응답이지만 누군가에게 목적을 제공 할 수도 있습니다. 이것은 내가 생각하기에 매우 깨끗하다고 ​​생각하는 방법입니다.

import time

def timed(fun, *args):
    s = time.time()
    r = fun(*args)
    print('{} execution took {} seconds.'.format(fun.__name__, time.time()-s))
    return(r)

timed(print, "Hello")

"인쇄"는 Python 2.7이 아니라 Python 3의 함수입니다. 그러나 다른 기능과 함께 작동합니다. 건배!


timeit 을 사용하는 또 다른 방법 :

from timeit import timeit

def func():
    return 1 + 1

time = timeit(func, number=1)
print(time)

시간을 사람이 읽을 수있는 시간으로 변환 할 수도 있습니다.

import time, datetime

start = time.clock()

def num_multi1(max):
    result = 0
    for num in range(0, 1000):
        if (num % 3 == 0 or num % 5 == 0):
            result += num

    print "Sum is %d " % result

num_multi1(1000)

end = time.clock()
value = end - start
timestamp = datetime.datetime.fromtimestamp(value)
print timestamp.strftime('%Y-%m-%d %H:%M:%S')

이를 위해 라이브러리를 만들었습니다. 함수를 측정하고 싶다면 이렇게하면됩니다.


from pythonbenchmark import compare, measure
import time

a,b,c,d,e = 10,10,10,10,10
something = [a,b,c,d,e]

@measure
def myFunction(something):
    time.sleep(0.4)

@measure
def myOptimizedFunction(something):
    time.sleep(0.2)

myFunction(input)
myOptimizedFunction(input)

https://github.com/Karlheinzniebuhr/pythonbenchmark


모든 함수 호출에 대한 통찰력을 얻으려면 다음을 수행하십시오.

%load_ext snakeviz
%%snakeviz

그냥 그 소요 코드의 2 개 라인을 A의 Jupyter 노트북 , 그리고 좋은 대화 형 다이어그램을 생성합니다. 예를 들면 :

여기에 이미지 설명 입력

다음은 코드입니다. 다시 말하지만로 시작하는 두 줄 %은 snakeviz를 사용하는 데 필요한 유일한 추가 코드 줄입니다.

# !pip install snakeviz
%load_ext snakeviz
import glob
import hashlib

%%snakeviz

files = glob.glob('*.txt')
def print_files_hashed(files):
    for file in files:
        with open(file) as f:
            print(hashlib.md5(f.read().encode('utf-8')).hexdigest())
print_files_hashed(files)

노트북 외부에서 snakeviz를 실행하는 것도 가능해 보입니다. snakeviz 웹 사이트 에 대한 추가 정보 .


timeit을 사용할 수 있습니다.

다음은 Python REPL을 사용하여 매개 변수를 취하는 naive_func를 테스트하는 방법에 대한 예입니다.

>>> import timeit                                                                                         

>>> def naive_func(x):                                                                                    
...     a = 0                                                                                             
...     for i in range(a):                                                                                
...         a += i                                                                                        
...     return a                                                                                          

>>> def wrapper(func, *args, **kwargs):                                                                   
...     def wrapper():                                                                                    
...         return func(*args, **kwargs)                                                                  
...     return wrapper                                                                                    

>>> wrapped = wrapper(naive_func, 1_000)                                                                  

>>> timeit.timeit(wrapped, number=1_000_000)                                                              
0.4458435332577161  

함수에 매개 변수가 없으면 래퍼 함수가 필요하지 않습니다.


내가 생각할 수있는 유일한 방법은 time.time().

import time
start = time.time()
sleep(5) #just to give it some delay to show it working
finish = time.time()
elapsed = finish - start
print(elapsed)

도움이 되길 바랍니다.


이 고유 한 클래스 기반 접근 방식은 인쇄 가능한 문자열 표현, 사용자 정의 가능한 반올림 및 문자열 또는 부동 소수점으로 경과 시간에 대한 편리한 액세스를 제공합니다. Python 3.7로 개발되었습니다.

import datetime
import timeit


class Timer:
    """Measure time used."""
    # Ref: https://stackoverflow.com/a/57931660/

    def __init__(self, round_ndigits: int = 0):
        self._round_ndigits = round_ndigits
        self._start_time = timeit.default_timer()

    def __call__(self) -> float:
        return timeit.default_timer() - self._start_time

    def __str__(self) -> str:
        return str(datetime.timedelta(seconds=round(self(), self._round_ndigits)))

용법:

>>> timer = Timer()

>>> # Access as a string
>>> print(f'Time elapsed is {timer}.')
Time elapsed is 0:00:03.
>>> print(f'Time elapsed is {timer}.')
Time elapsed is 0:00:04.

>>> # Access as a float
>>> timer()
6.841332235
>>> timer()
7.970274425

이외에 %timeit에서 ipython 당신은 또한 사용할 수있는 %%timeit여러 줄의 코드 조각을 위해 :

In [1]: %%timeit
   ...: complex_func()
   ...: 2 + 2 == 5
   ...:
   ...:

1 s ± 1.93 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

또한 jupyter 노트북 에서도 같은 방식 으로 사용할 수 있습니다 . 셀 시작 부분에 마법%%timeit걸면 됩니다 .


timeit을 더 잘 사용하십시오. (동일한 명령에 대해 여러 번 실행하고 결과를 제공합니다).

예는 다음과 같습니다.

%timeit import pandas as pd

참고 URL : https://stackoverflow.com/questions/7370801/measure-time-elapsed-in-python

반응형