Отримати час виконання блоку коду в Python 2.7


78

Я хотів би виміряти час, що минув для оцінки блоку коду в програмі Python, можливо, розділяючи час користувача процесора, час процесора системи та час, що минув.

Я знаю timeitмодуль, але у мене є багато самостійно написаних функцій, і їх не дуже легко передати в процесі налаштування.

Я волів би щось, що можна було б використовувати, наприклад:

#up to here I have done something....
start_counting() #or whatever command used to mark that I want to measure
                   #the time elapsed in the next rows
# code I want to evaluate
user,system,elapsed = stop_counting() #or whatever command says:
                                      #stop the timer and return the times

Час роботи процесора користувача та системи не є важливим (хоча я хотів би їх виміряти), але за минулий час я хотів би мати можливість зробити щось подібне, а не використовувати складні команди або модулі.

Відповіді:


167

Щоб отримати час, що минув у секундах, ви можете використовувати timeit.default_timer():

import timeit
start_time = timeit.default_timer()
# code you want to evaluate
elapsed = timeit.default_timer() - start_time

timeit.default_timer()використовується замість time.time()або time.clock()тому, що він вибере функцію синхронізації, яка має вищу роздільну здатність для будь-якої платформи.


4
Я читав, що це не найкращий підхід для блоків коду, на виконання яких йде лише частка секунди. Також я думаю, що за допомогою часового модуля є кращим метод .clock ()? stackoverflow.com/questions/85451 / ...
lucacerone

4
Мою відповідь змінено на використання timeit.default_timer(), яке буде вибирати між time.time()або time.clock()залежно від того, яка з більш високою роздільною здатністю на платформі, яку ви використовуєте.
Ендрю Кларк,

24

Я завжди використовую декоратор, щоб виконати якусь додаткову роботу для існуючої функції, зокрема, щоб отримати час виконання. Це пітонічно і просто.

import time

def time_usage(func):
    def wrapper(*args, **kwargs):
        beg_ts = time.time()
        retval = func(*args, **kwargs)
        end_ts = time.time()
        print("elapsed time: %f" % (end_ts - beg_ts))
        return retval
    return wrapper

@time_usage
def test():
    for i in xrange(0, 10000):
        pass

if __name__ == "__main__":
    test()

3
Вибачте, я все ще не знаю, як користуватися декораторами :(
лукацерон

4
@LucaCerone є чудове пояснення щодо прикраси stackoverflow.com/questions/739654/… . Спробуйте прочитати це терпляче, і ви зрозумієте декоратора.
Yarkee

Можливо, додайте a retval=...та return retvalобгортку. Якщо ви використовуєте декоратор як є, він відкине значення повернення функції.
Dave X

11

Я знову і знову вирішував цю проблему, тож нарешті створив для неї бібліотеку . Встановити за допомогою pip install timer_cm. Тоді:

from time import sleep
from timer_cm import Timer

with Timer('Long task') as timer:
    with timer.child('First step'):
        sleep(1)
    for _ in range(5):
        with timer.child('Baby steps'):
            sleep(.5)

Вихід:

Long task: 3.520s
  Baby steps: 2.518s (71%)
  First step: 1.001s (28%)

здавалося б , доречне питання я підняв: stackoverflow.com/questions/48260833 / ...
lurix66

Чудово працює, крім помилки ('таймер імпорту' ---> 'таймер імпорту') та відсутнього пакета ( import time)
user3768495

Це фантастика. Я створив випуск github у вашому репозиторії із заглушкою, яку люди можуть використовувати при імпорті, якщо хочуть зробити її необов’язковою.
Крейг Рінгер,

9

Ви можете досягти цього за допомогою Context Manager, наприклад:

from contextlib import contextmanager
import time
import logging
@contextmanager
def _log_time_usage(prefix=""):
    '''log the time usage in a code block
    prefix: the prefix text to show
    '''
    start = time.time()
    try:
        yield
    finally:
        end = time.time()
        elapsed_seconds = float("%.2f" % (end - start))
        logging.debug('%s: elapsed seconds: %s', prefix, elapsed_seconds)

приклад використання:

with _log_time_usage("sleep 1: "):
    time.sleep(1)

Це має бути prefix, а не item_name в останньому рядку.
Георгій Петров

1

Є ще один варіант, який я зараз дуже люблю для простоти - ipython. У ipython ви отримали багато корисного, плюс:

%time <expression> - щоб отримати прямий процес процесора та стіни на вираз

%timeit <expression> - отримати процес процесора та стінний час у циклі виразу


0

Python 3 - просте рішення із використанням стандартної бібліотеки

Варіант 1: Потрійне цитування коду

import inspect
import timeit


code_block = inspect.cleandoc("""
    base = 123456789
    exponent = 100
    return base ** exponent
    """)
print(f'\Code block: {timeit.timeit(code_block, number=1, globals=globals())} elapsed seconds')

inspect.cleandoc обробляє видалення зайвих вкладок та пробілів, завдяки чому блоки коду можуть бути скопійовані та вставлені без помилок відступу.

 

Варіант 2: Розмістіть блок коду у функції

import timeit


def my_function():
    base = 123456789
    exponent = 100
    return base ** exponent


if __name__ == '__main__':
    print(f'With lambda wrapper: {timeit.timeit(lambda: my_function(), number=1)} elapsed seconds')

Зверніть увагу, що виклик функції додасть додатковий час виконання порівняно із тимчасовим визначенням безпосередньо тіла функції.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.