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
내 블로그의 게시물 보기:
나의 방법:
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)
사용하는 경우timeit.timeit
if 명령어
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
'programing' 카테고리의 다른 글
문자열을 이진으로 변환한 다음 PHP를 사용하여 다시 변환 (0) | 2023.08.02 |
---|---|
sql의 union 절 (0) | 2023.08.02 |
PHP에서 SQL Server에 연결하는 동안 "Adaptive Server를 사용할 수 없거나 존재하지 않습니다" 오류가 발생했습니다. (0) | 2023.08.02 |
파이썬에서 여러 변수를 저장하고 복원하려면 어떻게 해야 합니까? (0) | 2023.08.02 |
실행 중인 도커 컨테이너에서 환경 변수를 설정하는 방법 (0) | 2023.08.02 |