Функция измерения времени Python
Я хочу создать функцию python, чтобы проверить время, проведенное в каждой функции, и распечатать ее имя со своим временем, как я могу напечатать имя функции, и если есть другой способ сделать это, пожалуйста, скажите мне
def measureTime(a):
start = time.clock()
a()
elapsed = time.clock()
elapsed = elapsed - start
print "Time spent in (function name) is: ", elapsed
7 ответов:
прежде всего, я настоятельно рекомендую использовать профайлер или по крайней мере использовать timeit.
однако, если вы хотите написать свой собственный метод синхронизации строго учиться, вот где-то, чтобы начать использовать декоратор.
Python 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
Python 3:
def timing(f): def wrap(*args): time1 = time.time() ret = f(*args) 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.
после игры с
timeit
модуль, мне не нравится его интерфейс, который не так элегантен по сравнению со следующими двумя методами.следующий код в Python 3.
метод декоратора
это почти то же самое с методом @Майк. Здесь я добавляю
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)
выглядит не так здорово...Что делать, если вы находитесь в Python 2, который не имеет
nonlocal
ключевое слово.вместо этого, используя второй метод подходит здесь очень хорошо:
images = get_images() with timeit_context('foobar'): bigImage = ImagePacker.pack(images, width=4096) drawer.draw(bigImage)
Я не вижу в чем проблема с
timeit
модуль. Это, наверное, самый простой способ сделать это.import timeit timeit.timeit(a, number=1)
его также можно отправить аргументы в функции. Все, что вам нужно, это обернуть свою функцию с помощью декораторов. Более подробное объяснение здесь: http://www.pythoncentral.io/time-a-python-function/
единственный случай, когда вам может быть интересно написать свои собственные операторы синхронизации, - это если вы хотите запустить функцию только один раз, а также хотите получить его возвращаемое значение.
преимущества использования
timeit
модуль заключается в том, что он позволяет повторить количество казней. Это может быть необходимо, поскольку другие процессы могут повлиять на точность синхронизации. Итак, вы должны запустить его несколько раз и посмотреть на самое низкое значение.
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)
метод декоратора с использованием библиотеки 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
смотрите пост в моем блоге:
есть простой инструмент для синхронизации. 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
надеюсь, что это поможет
мой способ сделать это:
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()
перед выполнением функции / loops, иprintTime(start)
сразу после блока.и вы получили ответ.