programing

Python 시간 측정 함수

stoneblock 2023. 8. 2. 08:40

Python 시간 측정 함수

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

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

우선 프로파일러를 사용하거나 최소한 시간을 사용하는 것이 좋습니다.

하지만 만약 여러분이 배우기 위해 엄격하게 여러분만의 타이밍 방법을 쓰고 싶다면, 여기 장식가를 사용하기 시작할 수 있는 곳이 있습니다.

파이썬 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 decorator를 사용하십시오.

@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에서), 또는 함이에파가면려져오또로는문자 2열서), 수f.__name__Python 3 버전.

게임을 한 후에.timeit모듈, 나는 그것의 인터페이스가 마음에 들지 않는데, 이것은 다음 두 가지 방법에 비해 그렇게 우아하지 않습니다.

다음 코드는 파이썬 3에 있습니다.

데코레이터 방식

이것은 @Mike의 방법과 거의 같습니다.에 추합니다를 추가합니다.kwargs그리고.functools더 좋게 포장합니다.

def timeit(func):
    @functools.wraps(func)
    def new_func(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        elapsed_time = time.time() - start_time
        print('function [{}] finished in {} ms'.format(
            func.__name__, int(elapsed_time * 1_000)))
        return result
    return new_func

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

컨텍스트 관리자 방법

from contextlib import contextmanager

@contextmanager
def timeit_context(name):
    start_time = time.time()
    yield
    elapsed_time = time.time() - start_time
    print('[{}] finished in {} ms'.format(name, int(elapsed_time * 1_000)))

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

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

리고그 코는드에 with블록 시간이 지정됩니다.

결론

첫 번째 방법을 사용하면 장식자를 쉽게 주석 처리하여 일반 코드를 얻을 수 있습니다.그러나 함수의 시간만 지정할 수 있습니다.코드의 일부를 함수로 만들 수 없는 경우 두 번째 방법을 선택할 수 있습니다.

예를 들어, 지금 당신은

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

이제 당신은 시간을 맞추고 싶습니다.big_image = ...이 . 함수로 변경하면 다음과 같습니다.

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

별로 좋지 않은 것 같은데요...2에 , 파이썬 2에 요?nonlocal 키워드

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

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

무슨 문제가 있는지 모르겠어요.timeit이 가장 입니다.이것이 아마도 가장 간단한 방법일 것입니다.

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

함수에 인수를 보낼 수도 있습니다.당신이 필요한 것은 장식기를 사용하여 당신의 기능을 마무리하는 것입니다.자세한 설명은 http://www.pythoncentral.io/time-a-python-function/ 에서 확인할 수 있습니다.

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

timeit모듈을 사용하면 실행 횟수를 반복할 수 있습니다.다른 프로세스가 타이밍 정확도를 방해할 수 있으므로 이 작업이 필요할 수 있습니다.따라서 여러 번 실행하고 가장 낮은 값을 확인해야 합니다.

Time은 두 가지 큰 결점을 가지고 있습니다. 함수의 반환 값을 반환하지 않고 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)

타이밍을 맞추기 위한 쉬운 도구가 있습니다.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

도움이 되길 바랍니다.

데코레이터 파이썬 라이브러리를 사용한 데코레이터 방법:

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 블로그에 게시

구글 플러스에 올린 나의 글

나의 방법:

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)블록 바로 뒤에

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

@Jonathan Ray에 대해 자세히 설명하자면, 저는 이것이 속임수를 조금 더 잘 한다고 생각합니다.

import time
import inspect

def timed(f:callable):
    start = time.time()
    ret = f()
    elapsed = 1000*(time.time() - start)
    source_code=inspect.getsource(f).strip('\n') 
    logger.info(source_code+":  "+str(elapsed)+" seconds")
    return ret

규칙적인 코드 라인을 사용할 수 있습니다.a = np.sin(np.pi)그리고 그것을 좀 더 간단하게 변형시킵니다.

a = timed(lambda: np.sin(np.pi))

타이밍이 로거에 인쇄되고 추가 작업에 필요할 수 있는 변수에 대한 결과 할당을 동일하게 유지할 수 있습니다.

파이썬 3.8에서 사용할 수 있을 것 같습니다.:=하지만 아직 3.8은 없습니다.

다음은 다음과 같은 타이머 클래스입니다.

  • 사용편리 : 직접 또는 데코레이터 기능으로 사용, 100라인 미만
  • 총 통화, 총 시간, 평균 시간 및 표준 편차를 많이 측정합니다.
  • 인쇄 시간이 짧습니다.
  • 스레드 세이프

사용 방법은 다음과 같습니다.

# Create the timer
timer1 = Timer("a name", log_every=2)

# Use "with"
with timer1:
   print("timer1")

# Reuse as a decorator
@timer1
def my_func():
  print("my_func")

# Instantiate as a decorator
@Timer("another timer", log_every=1)
def my_func2():
  print("my_func2")

my_func()
my_func2()
my_func()

아래는 수업입니다.

from datetime import datetime
import time, logging, math, threading
class Timer(object):
    '''A general timer class. Does not really belong in a judicata file here.'''
    def __init__(self, name, log_every = 1):
        self.name = name
        self.log_every = 1
        self.calls = 0
        self.total_time = 0
        self.total_squared_time = 0
        self.min, self.max = None, 0
        # Make timer thread-safe by storing the times in thread-local storage.
        self._local = threading.local()
        self._lock = threading.Lock()

    def __enter__(self):
        """Start a new timer"""
        self._local.start = datetime.utcnow()

    def __exit__(self, exc_type, exc_val, exc_tb):
        """Stop the timer, and report the elapsed time"""
        elapsed_time = (datetime.utcnow() - self._local.start).total_seconds()
        with self._lock:
            self.calls += 1
            self.total_time += elapsed_time
            if self.min == None or elapsed_time < self.min:
                self.min = elapsed_time
            if elapsed_time > self.max:
                self.max = elapsed_time
            self.total_squared_time += elapsed_time * elapsed_time
            if self.log_every and (self.calls % self.log_every) == 0:
                self.log()

    def __call__(self, fn):
        '''For use as a decorator.'''
        def decorated_timer_function(*args, **kwargs):
            with self:
                return fn(*args, **kwargs)
        return decorated_timer_function

    @classmethod
    def time_str(cls, secs):
        if isinstance(secs, six.string_types):
            try:
                secs = float(secs)
            except:
                return "(bad time: %s)"%secs
        sign = lambda x: x
        if secs < 0:
            secs = -secs
            sign = lambda x: ("-" + x)
        return sign("%d secs"%int(secs) if secs >= 120 else
                    "%.2f secs" % secs if secs >= 1 else
                    "%d ms" % int(secs * 1000) if secs >= .01 else
                    "%.2f ms" % (secs * 1000) if secs >= .0001 else
                    "%d ns" % int(secs * 1000 * 10000) if secs >= 1e-9 else
                    "%s" % secs)

    def log(self):
        if not self.calls:
            logging.info("<Timer %s: no calls>"%self.name)
            return
        avg = 1.0 * self.total_time / self.calls
        var = 1.0 * self.total_squared_time / self.calls - avg*avg
        std_dev = self.time_str(math.sqrt(var))
        total = self.time_str(self.total_time)
        min, max, avg = [self.time_str(t) for t in [self.min, self.max, avg]]
        logging.info("<Timer %s: N=%s, total=%s, avg=%s, min/max=%s/%s, std=%s>"
                     %(self.name, self.calls, total, avg, min, max, std_dev))

와 함께 사용할 수 있습니다.

from timeit import default_timer
from contextlib import contextmanager

@contextmanager
def timer():
    start_time = default_timer()
    try:
        yield
    finally:
        print("--- %s seconds ---" % (default_timer() - start_time))

함께 사용with문:

def looper():
    for i in range(0, 100000000):
        pass

with timer():
    looper()

출력:

--- 2.651526927947998 seconds ---

일반 솔루션은 다음과 같습니다.

def timed(fn):
    # make sure wherever u used this, imports will be ready
    from time import perf_counter
    from functools import wraps
    # wraps preserves the metadata of fn
    @wraps(fn)
    def inner(*args, **kwargs):
        start = perf_counter()
        result = fn(*args, **kwargs)
        end = perf_counter()
        elapsed = end - start
        args_ = [str(a) for a in args]
        kwargs_ = ["{0}={1}".format(k, v) for (k, v) in kwargs.items()]
        all_args = args_ + kwargs_
        args_str = ",".join(all_args)
        print("{0} ({1}) took {2:.6f} to run.".format(fn.__name__, args_str, elapsed))
        return result
    return inner

함수 정의:

@timed
def sum_up(a,b):
     return a+b

이제 그것을 부릅니다.

sum_up(2,9)

enter image description here

사용하는 경우timeit.timeitif 명령어

timeit.timeit(function_to_test, n=10000)

오류를 제기합니다.ValueError: stmt is neither a string nor callable

또는 명령

timeit.timeit('function_to_test', n=10000)

오류를 제기합니다.name 'function_to_test' is not defined다음이 필요합니다.

교체하다 function_to_test또는'function_to_test'와 함께str(function_to_test),그것은

timeit.timeit(str(function_to_test), n=10000)

또는 Python 버전 >= 3.6인 경우, 다른 방법은 f 문자열을 다음과 같이 사용하는 것입니다.

timeit.timeit(f'{function_to_test}', n=10000)

버전 정보는 람다를 사용합니다.timeit.timeit(lambda: function_to_test, n=10000)그것은 효과가 있지만, 내 테스트에서, 그것은 훨씬 더 오랜 시간이 걸립니다.

구체적인 예는 다음과 같습니다.

import timeit

def function_to_test(n):
    s = 1
    for i in range(n):
        s += 1
    return s
    
print("time run function_to_test: ", timeit.timeit(str(function_to_test(1000000)), number=10000))
print("time run function_to_test: ", timeit.timeit(f'{function_to_test(1000000)}', number=10000))

이 코드가 유용할 수 있습니다.

import time

def start_time_measure(print_res = True):
  start_time = time.time()
  def end_time_measure():
      elapsed_time = time.time() - start_time
      if print_res:
          print("Elapsed time: ", elapsed_time)
      return elapsed_time
  return end_time_measure

예:

end_time_measure = start_time_measure()

# Here is some job to do
a = []
for i in range(100000):
  a.append(i)

end_time_measure()

다음 두 가지 기능을 호출하여 코드의 모든 섹션에 대한 타이머를 실행할 수 있습니다.start_time_measure마감을 생성하고 반환합니다.start_time_measure타이머를 중지하고 결과를 인쇄할 수 있는 기능 + 시간 값을 반환합니다.

언급URL : https://stackoverflow.com/questions/5478351/python-time-measure-function