Я хочу создать функцию python для проверки времени, затраченного на каждую функцию, и напечатать его имя со временем, как я могу напечатать имя функции, и если есть другой способ сделать это, пожалуйста, скажите мне
def measureTime(a):
start = time.clock()
a()
elapsed = time.clock()
elapsed = elapsed - start
print "Time spent in (function name) is: ", elapsed
Ответ 1
Прежде всего, я настоятельно рекомендую использовать профилировщик или использовать timeit.
Однако, если вы хотите написать свой собственный метод синхронизации строго, чтобы узнать, вот где начать, используя декоратор.
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
Примечание. Я вызываю f.func_name
, чтобы получить имя функции в виде строки (в Python 2) или f.__name__
в Python 3.
Ответ 2
После воспроизведения с модулем timeit
мне не нравится его интерфейс, который не настолько элегантен по сравнению со следующими двумя способами.
Следующий код находится в Python 3.
Метод декоратора
Это почти то же самое с методом @Mike. Здесь я добавляю kwargs
и functools
wrap, чтобы сделать его лучше.
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)
Ответ 3
Я не вижу, что проблема с модулем timeit
. Вероятно, это самый простой способ сделать это.
import timeit
timeit.timeit(a, number=1)
Также возможно отправить аргументы в функции. Все, что вам нужно, это обернуть вашу функцию, используя декораторы. Больше объяснений здесь: http://www.pythoncentral.io/time-a-python-function/
Единственный случай, когда вам может быть интересно записать свои собственные операторы синхронизации, - это если вы хотите запустить функцию только один раз и также хотите получить ее возвращаемое значение.
Преимущество использования модуля timeit
заключается в том, что он позволяет repeat количество исполнений. Это может быть необходимо, потому что другие процессы могут мешать вашей точности синхронизации. Таким образом, вы должны запускать его несколько раз и смотреть на самое низкое значение.
Ответ 4
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)
Ответ 5
Используйте профайлер, например , вместо того, чтобы пытаться реализовать такую функциональность самостоятельно.
Ответ 6
Метод декоратора с использованием декоратора Библиотека 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
Ответ 7
Существует простой инструмент для синхронизации. 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
Надеюсь, что это поможет
Ответ 8
Мой способ сделать это:
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)
сразу после блока.
и вы получили ответ.