Измерение прошедшего времени в python
Существует ли простой способ/модуль правильно измерить прошедшее время в python? Я знаю, что я могу просто называть time.time()
дважды и учитывать разницу, но это приведет к неправильным результатам, если системное время будет изменено. Конечно, это происходит не очень часто, но это указывает на то, что я измеряю неправильную вещь.
Использование time.time()
для измерения продолжительности невероятно круговое, когда вы думаете об этом. Вы принимаете разницу между двумя измерениями абсолютного времени, которые, в свою очередь, построены по измерениям продолжительности (выполняются таймерами) и известным абсолютным временам (устанавливаются вручную или через ntp), что вас совсем не интересует.
Итак, есть ли способ запросить это "время таймера" напрямую? Я бы предположил, что его можно представить как миллисекунду или микросекунду, которая не имеет значимого абсолютного представления (и, следовательно, ее не нужно настраивать с системным временем). Оглядываясь немного, кажется, что это именно то, что System.nanoTime()
делает в Java, но я не нашел соответствующую функцию Python, хотя он должен (технически-технически) быть проще, чем time.time()
.
Изменить: Чтобы избежать путаницы и ответить на приведенные ниже ответы: речь идет не о изменениях DST, и я также не хочу процессорного времени - я хочу истекшее физическое время. Он не должен быть очень мелкозернистым и даже не особенно точным. Это просто не должно давать мне отрицательную длительность, или длительность, которая отключена на несколько порядков (выше гранулярности), только потому, что кто-то решил установить системные часы на другое значение. Здесь, что Python docs говорит о "time.time()":
"Хотя эта функция обычно возвращает неубывающие значения, она может вернуть более низкое значение, чем предыдущий вызов, если системные часы были установлены обратно между двумя называет"
Это именно то, чего я хочу избежать, поскольку это может привести к странным вещам, таким как отрицательные значения во временных расчетах. Я могу обойти это на данный момент, но я считаю, что это хорошая идея, чтобы научиться использовать правильные решения там, где это возможно, поскольку kludges вернутся, чтобы укусить вас в один прекрасный день.
Edit2: Некоторые исследования показывают, что вы можете получить независимое от системы измерение, которое я хочу в Windows с помощью GetTickCount64(), под Linux вы можете получить его в возвращаемом значении times(). Тем не менее, я до сих пор не могу найти модуль, который предоставляет эту функциональность в Python.
Ответы
Ответ 1
То, что вы ищете, - это монотонный таймер. A монотонный отсчет времени не прыгает или не возвращается назад.
Было предпринято несколько попыток реализовать кросс-платформенные монотомные часы для Python на основе ссылки на ОС. (Windows, POSIX и BSD совершенно разные) См. Обсуждения и некоторые попытки монотонного времени в этом сообщении SO.
В основном, вы можете просто использовать os.times():
os.times()
Возвращает 5-битный номер чисел с плавающей запятой, указывающий накопленный (процессор или другой) раз, в секундах. Элементы: время пользователя, системное время, время для детей, время в системе для детей, и истекшее реальное время с фиксированной точки в прошлом, в этом порядке. См. Временные страницы справочной системы Unix (2) или соответствующие окна Windows Документация API платформы. В Windows только первые два элемента заполнены, остальные равны нулю.
Доступность: Unix, Windows
Но это не заполняет необходимое истекшее реальное время (пятый кортеж) в Windows.
Если вам нужна поддержка Windows, рассмотрите ctypes
, и вы можете напрямую вызвать GetTickCount64(), как это было сделано в этот рецепт.
Ответ 2
Для измерения прошедшего времени процессора просмотрите time.clock(). Это эквивалент Linux times() поля пользовательского времени.
Для бенчмаркинга используйте timeit.
модуль datetime, который является частью Python 2.3+, также имеет микросекундное время, если поддерживается платформой.
Пример:
>>> import datetime as dt
>>> n1=dt.datetime.now()
>>> n2=dt.datetime.now()
>>> (n2-n1).microseconds
678521
>>> (n2.microsecond-n1.microsecond)/1e6
0.678521
ie, it took me .678521 seconds to type the second n2= line -- slow
>>> n1.resolution
datetime.timedelta(0, 0, 1)
1/1e6 resolution is claimed.
Если вас беспокоит изменение системного времени (от DS → ST), просто проверьте объект, возвращенный datetime.Presumable, системное время может иметь небольшую корректировку от NTP. Это должно быть уменьшено, а исправления применяются постепенно, но ntp sync beats может иметь эффект с очень малыми (миллисекундами или микросекундами) ссылками на время.
Вы также можете ссылаться на функцию Alex Martelli C, если хотите что-то из этого разрешения. Я бы не зашел слишком далеко, чтобы изобретать велосипед. Точное время является основным, и большинство современных ОС выполняют довольно хорошую работу.
Edit
Основываясь на ваших пояснениях, похоже, что вам нужна простая боковая проверка, если системные часы изменились. Просто сравните с дружественным локальным сервером ntp:
import socket
import struct
import time
ntp="pool.ntp.org" # or whatever ntp server you have handy
client = socket.socket( socket.AF_INET, socket.SOCK_DGRAM )
data = '\x1b' + 47 * '\0'
client.sendto( data, ( ntp, 123 ))
data, address = client.recvfrom( 1024 )
if data:
print 'Response received from:', address
t = struct.unpack( '!12I', data )[10]
t -= 2208988800L #seconds since Epoch
print '\tTime=%s' % time.ctime(t)
NTP является точным до миллисекунд через Интернет и имеет разрешение представления разрешения 2-32 секунды (233 пикосекунды). Должно быть достаточно хорошо?
Помните, что структура данных 64 бит NTP будет переполняться в 2036 году и каждые 136 лет после этого - если вы действительно хотите надежное решение, лучше проверить переполнение...
Ответ 3
Python 3.3 добавил монотонный таймер в стандартную библиотеку, что делает именно то, что я искал. Спасибо Paddy3118 за то, что указали это в "Как получить монотонные длительности времени в python?" .
Ответ 4
>>> import datetime
>>> t1=datetime.datetime.utcnow()
>>> t2=datetime.datetime.utcnow()
>>> t2-t1
datetime.timedelta(0, 8, 600000)
Использование UTC позволяет избежать этих периодов смущения, когда часы сдвигаются из-за летнего времени.
Что касается использования альтернативного метода, а не вычитания двух часов, имейте в виду, что ОС фактически содержит часы, которые инициализируются из аппаратных часов на ПК. Современные реализации ОС также будут поддерживать синхронизацию этих часов с некоторым официальным источником, чтобы он не дрейфовал. Это намного более точно, чем любой таймер, который может быть запущен ПК.
Ответ 5
Примеры функций, которые вы укажете в своем редактировании, - это две совершенно разные вещи:
- Linux times() возвращает время процесса в миллисекундах CPU. Эквивалент Python - time.clock() или
os.times()
.
- Windows GetTickCount64() возвращает время безотказной работы системы.
Хотя две различные функции, оба (потенциально) могут быть использованы для выявления системных часов, которые имели "отрыжку" с помощью этих методов:
Во-первых:
Вы можете взять системное время с time.time()
и время процессора с помощью time.clock()
. Поскольку время настенных часов ВСЕГДА будет больше или равно процессорному времени, отбросьте любые измерения, где интервал между двумя показаниями time.time()
меньше, чем показания проверки парных time.clock()
.
Пример:
t1=time.time()
t1check=time.clock()
# your timed event...
t2=time.time()
t2check=time.clock()
if t2-t1 < t2check - t1check:
print "Things are rotten in Denmark"
# discard that sample
else:
# do what you do with t2 - t1...
Второе:
Обеспечение бесперебойной работы системы также является многообещающим, если вы обеспокоены системными часами, поскольку пользователь reset в большинстве случаев не считает reset количество отсчетов времени безотказной работы. (что я знаю...)
Теперь более сложный вопрос: получение времени безотказной работы системы независимо от платформы - особенно без появления новой оболочки - на второй секунде. Хммм...
Вероятно, лучший вариант psutil. Просмотр источника, они используют uptime = GetTickCount() / 1000.00f;
для Windows и sysctl "kern.boottime"
для BSD/OS X и т.д. К сожалению, все они имеют разрешение 1 секунду,
Ответ 6
from datetime import datetime
start = datetime.now()
print 'hello'
end = datetime.now()
delta = end-start
print type(delta)
<type 'datetime.timedelta'>
import datetime
help(datetime.timedelta)
...elapsed seconds and microseconds...