Вимірювання минулого часу за допомогою модуля Час


337

За допомогою модуля Time в python можна виміряти минулий час? Якщо так, то як це зробити?

Мені потрібно зробити це, щоб, якщо курсор був у віджеті протягом певної тривалості, траплялася подія.


3
Зверніть увагу, що будь-яка відповідь з використанням time.time()неправильної. Найпростіший приклад - якщо системний час змінюється протягом періоду вимірювання.
OrangeDog

Для вашого початкового запитання щодо запуску події, якщо курсор залишається певний час на віджеті , я думаю , що docs.python.org/3/library/threading.html надає все необхідне. Багатопоточність та змінна умова із тимчасовим очікуванням може бути одним із рішень. Однак на ваші обставини відповісти на сьогодні незрозуміло.
Тора

2
Немає жодної причини, щоб хтось використовував time.time()для вимірювання минулого часу в сучасному пітоні (це впливає на зміни вручну, дрейф, стрибкові секунди тощо). Ця відповідь нижче повинна бути вищою, враховуючи, що це питання зараз є найкращим результатом в Google для вимірювання минулого часу.
NPras

Ви можете вимірювати час з Cprofile профайлер , а також: docs.python.org/3/library/profile.html#module-cProfile stackoverflow.com/questions/582336 / ...
Антон Тарасенко

1
@NPras забудьте "сучасний пітон". Використовувати це завжди було неправильно time.time().
OrangeDog

Відповіді:


514
start_time = time.time()
# your code
elapsed_time = time.time() - start_time

Ви також можете написати простий декоратор для спрощення вимірювання часу виконання різних функцій:

import time
from functools import wraps

PROF_DATA = {}

def profile(fn):
    @wraps(fn)
    def with_profiling(*args, **kwargs):
        start_time = time.time()

        ret = fn(*args, **kwargs)

        elapsed_time = time.time() - start_time

        if fn.__name__ not in PROF_DATA:
            PROF_DATA[fn.__name__] = [0, []]
        PROF_DATA[fn.__name__][0] += 1
        PROF_DATA[fn.__name__][1].append(elapsed_time)

        return ret

    return with_profiling

def print_prof_data():
    for fname, data in PROF_DATA.items():
        max_time = max(data[1])
        avg_time = sum(data[1]) / len(data[1])
        print "Function %s called %d times. " % (fname, data[0]),
        print 'Execution time max: %.3f, average: %.3f' % (max_time, avg_time)

def clear_prof_data():
    global PROF_DATA
    PROF_DATA = {}

Використання:

@profile
def your_function(...):
    ...

Ви можете одночасно профілювати більше однієї функції. Потім для друку вимірювань просто зателефонуйте print_prof_data ():


11
Ви також можете подивитися на профілі pip install profilehooks та його домашню сторінку тут
піжама

11
Зауважте, що, оскільки Python 3.3, слід, мабуть, використовувати time.monotonic()скоріше, ніж time.time()для вимірювання часу та тривалості. docs.python.org/3/library/time.html#time.monotonic
Debilski

39
Варто додати / зазначити, що одиниця вимірювання за минулий час становитиме секунди.
Ерік Крамер

4
@EricKramer дякую! величезний улюбленець пеєв моїх, пояснюючи вимірювання без визначення одиниці вимірювання. І коли хлопець .NET вперше занурив пальці в Python, я автоматично подумав "мілісекунди".
Адам Плочер

2
Не працює, якщо (наприклад) системний годинник змінено і може не мати роздільної роздільної здатності. Правильна відповідь: stackoverflow.com/a/47637891/476716
OrangeDog

97

time.time() зробить роботу.

import time

start = time.time()
# run your code
end = time.time()

elapsed = end - start

Ви можете поглянути на це питання, але я не думаю, що це буде необхідним.


6
Так, час в секундах
Ерік Креймер

Ви повинні змінити start_time.
Зоран Пандовський

time.time()це погана ідея, оскільки системний годинник може бути скинутий, що змусить вас піти назад у часі. time.monotonic()дбає про це (монотонне = це лише йде вперед). time.perf_counter()також є монотонним, але має ще більшу точність, тому це рекомендується для настінного годинника.
xjcl

76

Для користувачів, які бажають кращого форматування,

import time
start_time = time.time()
# your script
elapsed_time = time.time() - start_time
time.strftime("%H:%M:%S", time.gmtime(elapsed_time))

роздрукується протягом 2 секунд:

'00:00:02'

і протягом 7 хвилин одну секунду:

'00:07:01'

зауважте, що мінімальна одиниця часу з gmtime - секунди. Якщо вам потрібні мікросекунди, врахуйте наступне:

import datetime
start = datetime.datetime.now()
# some code
end = datetime.datetime.now()
elapsed = end - start
print(elapsed)
# or
print(elapsed.seconds,":",elapsed.microseconds) 

документація стропіл


1
Дякую за вашу відповідь, яка мене надихає. Я збираюся використовувати, e = time.time() - start_time ; print("%02d:%02d:%02d" % (e // 3600, (e % 3600 // 60), (e % 60 // 1)))що врожаї майже однакові, а також висвітлюють ситуацію, яка триває більше 24 годин.
Тора

@Tora, можливо, ви захочете перевірити формат "{}". () Замість% 02d для майбутніх проблем із сумісністю.
Rutger Hofste

2
Дякую тобі! Зараз я звикаю до нового. Формат '{: 02d}: {: 02d}: {: 02d}'. (E // 3600, (e% 3600 // 60), e% 60)
Тора

ви можете використовувати, time.monotonic()як в інших відповідях?
ендоліти

elapsed.secondsбуде неправильним, якщо тривалість більше одного дня. Хочете elapsed.total_seconds()бути стійкими
Еш Берлін-Тейлор

51

Для найкращого вимірювання минулого часу (починаючи з Python 3.3), використовуйте time.perf_counter().

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

Для вимірювань на порядок годин / днів вам не байдуже роздільна здатність другої секунди, тому використовуйте time.monotonic()натомість.

Повертайте значення (в дробових секундах) монотонного годинника, тобто годинника, який не може повернутися назад. На годинник не впливають оновлення системних годин. Референтна точка повернутого значення не визначена, тому справедлива лише різниця між результатами послідовних викликів.

У багатьох реалізаціях це насправді може бути те саме.

До 3.3, ви застрягли time.clock().

У Unix поверніть поточний час процесора у вигляді числа з плаваючою комою, вираженого в секундах. Точність, а насправді саме визначення значення "процесорного часу", залежить від однойменної функції С.

У Windows ця функція повертає настінні годинники, що минули з моменту першого виклику цієї функції, як номер з плаваючою точкою на основі функції Win32 QueryPerformanceCounter (). Роздільна здатність, як правило, краще, ніж одна мікросекунда.


Оновлення для Python 3.7

Новим у Python 3.7 є PEP 564 - Додайте нові функції часу з роздільною здатністю наносекунд.

Використання цих даних може додатково усунути помилки округлення та плаваючої точки, особливо якщо ви вимірюєте дуже короткі періоди, або ваша програма (або машина Windows) працює довго.

Роздільна здатність починає руйнуватися perf_counter()приблизно через 100 днів. Так, наприклад, після року перерви, найкоротший інтервал (який перевищує 0), який він може виміряти, буде більшим, ніж коли він почався.


Оновлення для Python 3.8

time.clock тепер пішов.


"У багатьох реалізаціях це насправді може бути те саме". Правда, на моєму ПК Linux Mint, time.monotonic () і time.perf_counter (), схоже, повертають однакові значення.
xjcl

7

Більш тривалий період.

import time
start_time = time.time()
...
e = int(time.time() - start_time)
print('{:02d}:{:02d}:{:02d}'.format(e // 3600, (e % 3600 // 60), e % 60))

надрукував би

00:03:15

якщо більше 24 годин

25:33:57

Це натхнене відповіддю Рутгера Хофста. Дякую, Рутгер!


6

Вам потрібно імпортувати час, а потім використовувати метод time.time (), щоб знати поточний час.

import time

start_time=time.time() #taking current time as starting time

#here your code

elapsed_time=time.time()-start_time #again taking current time - starting time 

3

Ще один хороший спосіб часу речей використовувати з структурою пітона.

зі структурою автоматично викликає методи __enter__ та __exit__, що саме є тим, що нам потрібно для того, щоб виправити речі.

Давайте створимо клас Таймера .

from time import time

class Timer():
    def __init__(self, message):
        self.message = message
    def __enter__(self):
        self.start = time()
        return None  # could return anything, to be used like this: with Timer("Message") as value:
    def __exit__(self, type, value, traceback):
        elapsed_time = (time() - self.start) * 1000
        print(self.message.format(elapsed_time))

Тоді можна використовувати клас Таймер так:

with Timer("Elapsed time to compute some prime numbers: {}ms"):
    primes = []
    for x in range(2, 500):
        if not any(x % p == 0 for p in primes):
            primes.append(x)
    print("Primes: {}".format(primes))

Результат такий:

Прайми: [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89 , 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227 , 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373 , 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499]

Час обчислення простих чисел: 5,01704216003418мс


2

Відповідь Вадима Шендера чудова. Ви також можете використовувати простіший декоратор, як показано нижче:

import datetime
def calc_timing(original_function):                            
    def new_function(*args,**kwargs):                        
        start = datetime.datetime.now()                     
        x = original_function(*args,**kwargs)                
        elapsed = datetime.datetime.now()                      
        print("Elapsed Time = {0}".format(elapsed-start))     
        return x                                             
    return new_function()  

@calc_timing
def a_func(*variables):
    print("do something big!")

1

У програмуванні є два основних способи вимірювання часу з різними результатами:

>>> print(time.process_time()); time.sleep(10); print(time.process_time())
0.11751394000000001
0.11764988400000001  # took  0 seconds and a bit
>>> print(time.perf_counter()); time.sleep(10); print(time.perf_counter())
3972.465770326
3982.468109075       # took 10 seconds and a bit
  • Час процесора . Це час, який цей конкретний процес витрачає активно на виконання процесора. Сон, очікування веб-запиту або час, коли виконуються лише інші процеси, не сприятимуть цьому.

    • Використовуйте time.process_time()
  • Час настінних годин : Це стосується того, скільки часу минуло "на годиннику, що висить на стіні", тобто поза реальним часом.

    • Використовуйте time.perf_counter()

      • time.time() також вимірює час настінного годинника, але його можна скинути, щоб ви могли піти назад у часі
      • time.monotonic() не може бути скинутий (монотонний = йде лише вперед), але має меншу точність, ніж time.perf_counter()

0

Ось оновлення розумного коду Вадима Шендера з табличним виведенням:

import collections
import time
from functools import wraps

PROF_DATA = collections.defaultdict(list)

def profile(fn):
    @wraps(fn)
    def with_profiling(*args, **kwargs):
        start_time = time.time()
        ret = fn(*args, **kwargs)
        elapsed_time = time.time() - start_time
        PROF_DATA[fn.__name__].append(elapsed_time)
        return ret
    return with_profiling

Metrics = collections.namedtuple("Metrics", "sum_time num_calls min_time max_time avg_time fname")

def print_profile_data():
    results = []
    for fname, elapsed_times in PROF_DATA.items():
        num_calls = len(elapsed_times)
        min_time = min(elapsed_times)
        max_time = max(elapsed_times)
        sum_time = sum(elapsed_times)
        avg_time = sum_time / num_calls
        metrics = Metrics(sum_time, num_calls, min_time, max_time, avg_time, fname)
        results.append(metrics)
    total_time = sum([m.sum_time for m in results])
    print("\t".join(["Percent", "Sum", "Calls", "Min", "Max", "Mean", "Function"]))
    for m in sorted(results, reverse=True):
        print("%.1f\t%.3f\t%d\t%.3f\t%.3f\t%.3f\t%s" % (100 * m.sum_time / total_time, m.sum_time, m.num_calls, m.min_time, m.max_time, m.avg_time, m.fname))
    print("%.3f Total Time" % total_time)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.