Библиотека time Python: время, паузы и таймеры
Запрос «time sleep python» охватывает паузы, текущую отметку и замер длительности операций. Для длительности используйте perf_counter(), для текущей отметки времени – time(), а sleep() приостанавливает текущий поток. Примеры помогут измерить функцию и скрипт, сравнить повторные прогоны, получить дату и отформатировать ее.
Модуль time входит в стандартную библиотеку Python: устанавливать его отдельно не нужно.
Часть функций опирается на системную библиотеку C. Диапазон дат, разрешение часов и некоторые возможности зависят от платформы.
- Сравнение часов
- Python: текущее время и основной таймер
- Таймер относительного времени
- Таймер процессора
- Python: время выполнения функции через perf_counter()
- Повторные замеры через timeit
- time sleep Python: как задать паузу
- Наносекундные функции time
- Модуль time Python: компоненты времени
- Работа с часовыми поясами
- Обработка и форматирование времени
- Как выбрать таймер под задачу
Сравнение часов
Выбирайте таймер в Python по тому, что хотите измерить. Календарная отметка, прошедший интервал и затраты процессора решают разные задачи.
| Функция | Можно перевести системной настройкой | Монотонная | Учитывает sleep | Для какой задачи |
|---|---|---|---|---|
time() | Да | Нет | Да, но возможны скачки системных часов | Отметка времени события |
monotonic() | Нет | Да | Да | Тайм-ауты и интервалы |
perf_counter() | Нет | Да | Да | Замер длительности операции, бенчмарк |
process_time() | Нет | Да | Нет | Процессорное время всего процесса |
thread_time() | Нет | Да | Нет | Процессорное время текущего потока |
Монотонные часы не идут назад при переводе системного времени. Два последовательных вызова могут вернуть одинаковое значение. Разрешение часов ограничивает различимость близких событий.
Функция get_clock_info() показывает свойства часов на вашем компьютере. Сохраните пример в clock_info.py и запустите командой python -m clock_info из папки файла. Команда python здесь и дальше должна запускать ваш Python 3.
import platform
import sys
import time
print("Python:", sys.version)
print("ОС:", platform.platform())
available_clocks = [
"time",
"monotonic",
"perf_counter",
"process_time",
]
if hasattr(time, "thread_time"):
available_clocks.append("thread_time")
for name in available_clocks:
info = time.get_clock_info(name)
print(f"\n{name}")
print(" Реализация:", info.implementation)
print(" Монотонные:", info.monotonic)
print(" Переводимые:", info.adjustable)
print(" Разрешение, с:", info.resolution)Вывод начинается с версии интерпретатора и названия ОС. Затем программа печатает свойства доступных часов.
Поле resolution описывает разрешение, но не гарантирует точность любого замера.
Не используйте time.clock(): функцию удалили в Python 3.8. Для процессорного времени берите process_time(), для длительности – perf_counter(). Назначение функций описывает официальная документация модуля time.
Python: текущее время и основной таймер
Функция time.time() возвращает секунды от начала эпохи числом float. Такую отметку удобно сохранять вместе с событием. Дробная часть представляет долю секунды, но ее точность зависит от платформы.
import time
created_at = time.time()
print("Отметка события:", created_at)
print("Сейчас:", time.ctime())
print("Через 15 секунд:", time.ctime(time.time() + 15))Функция ctime() без аргумента форматирует текущее локальное время. С аргументом она форматирует переданную отметку.
Последняя строка примера показывает будущую дату без ожидания 15 секунд.
Для задачи «time now» подходят два разных представления. Вызов time.time() дает число секунд, а datetime.now() – объект с полями даты и времени. Функции time.now() в модуле нет.
import time
from datetime import datetime, timezone
print("Секунды:", time.time())
print("Локальная дата:", datetime.now())
print("Дата с поясом UTC:", datetime.now(timezone.utc))Обычный datetime.now() возвращает локальное время без информации о поясе. Для однозначной записи события используйте объект с часовым поясом. Передача timezone.utc задает UTC явно.
Таймер относительного времени
Функция monotonic() подходит для отсчета тайм-аутов и прошедших интервалов. Перевод календарных часов не заставит ее значение уменьшиться. Начало отсчета у этих часов произвольно.
import time
start = time.monotonic()
time.sleep(0.1)
elapsed = time.monotonic() - start
print(f"Прошло: {elapsed:.6f} с")Программа выводит длительность паузы вместе с накладными расходами между замерами. Значение может немного превышать 0,1 секунды.
Не сравнивайте результат monotonic() с отметкой time.time(): функции используют разные начала отсчета.
Для тайм-аута сохраните крайний срок как time.monotonic() + timeout. При проверке сравнивайте его с новым вызовом monotonic(). Такой срок предназначен для внутреннего отсчета, а не для записи календарной даты.
Таймер процессора
Функция process_time() измеряет процессорное время текущего процесса. Она суммирует пользовательское и системное процессорное время.
Пауза sleep() сама по себе этот счетчик не увеличивает.
Сравните длительность операции и затраты процессора на одной задаче:
import time
wall_start = time.perf_counter()
cpu_start = time.process_time()
result = sum(number * number for number in range(500_000))
time.sleep(0.2)
cpu_elapsed = time.process_time() - cpu_start
wall_elapsed = time.perf_counter() - wall_start
print("Результат:", result)
print(f"Процессорное время: {cpu_elapsed:.6f} с")
print(f"Прошедшее время: {wall_elapsed:.6f} с")Счетчик perf_counter() включает паузу в прошедшее время.
Счетчик process_time() учитывает вычисления и работу измерительного кода. Поэтому нулевой результат для процессорного времени здесь не обязателен.
В многопоточной программе process_time() учитывает работу всех потоков процесса. Если нужен только текущий поток, используйте thread_time(), когда платформа его поддерживает.
Процессорное время многопоточного процесса может превышать прошедшее время.
Python: время выполнения функции через perf_counter()
Функция perf_counter() измеряет прошедшее время с высоким доступным разрешением. Для замера поставьте один вызов перед операцией, второй – после. Разность включает ожидание ввода-вывода и паузы.
Как измерить один вызов функции
Сохраните код в measure_function.py. Запустите его командой python measure_function.py из папки файла.
from time import perf_counter
def build_report(size):
return sum(number * number for number in range(size))
start = perf_counter()
result = build_report(500_000)
elapsed = perf_counter() - start
print("Результат:", result)
print(f"Время выполнения функции: {elapsed:.6f} с")Первая строка вывода содержит результат вычисления, вторая – длительность в секундах. Вывод находится за пределами измеряемого участка. Это исключает время печати из замера самой функции.
Как сделать декоратор-замерщик
Декоратор избавляет от повторения двух вызовов таймера возле каждой функции. Обертка сохраняет результат, аргументы и метаданные исходной функции.
from functools import wraps
from time import perf_counter
def timed(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = perf_counter()
try:
return func(*args, **kwargs)
finally:
elapsed = perf_counter() - start
print(f"{func.__name__}: {elapsed:.6f} с")
return wrapper
@timed
def build_report(size):
return sum(number * number for number in range(size))
result = build_report(500_000)
print("Результат:", result)Блок finally печатает длительность даже при исключении внутри функции. Исключение при этом продолжает распространяться.
Обертка предназначена для обычных синхронных функций: она не измерит выполнение тела корутины после await.
Python: время выполнения скрипта целиком
Если интересует основной код скрипта, поставьте таймер вокруг вызова main(). Этот замер не включает запуск интерпретатора и импорты перед таймером.
from time import perf_counter
def main():
result = sum(number * number for number in range(500_000))
print("Результат:", result)
if __name__ == "__main__":
start = perf_counter()
main()
elapsed = perf_counter() - start
print(f"Время main(): {elapsed:.6f} с")Для полного запуска измерьте дочерний процесс отдельным скриптом. Сохраните предыдущий пример в report.py, следующий – в measure_script.py рядом с ним.
from pathlib import Path
import subprocess
import sys
from time import perf_counter
script = Path(__file__).with_name("report.py")
start = perf_counter()
subprocess.run([sys.executable, str(script)], check=True)
elapsed = perf_counter() - start
print(f"Полный запуск скрипта: {elapsed:.6f} с")Выполните python measure_script.py. После вывода report.py появится длительность полного запуска. Она включает создание процесса, запуск интерпретатора, импорты и выполнение скрипта.
Повторные замеры через timeit
Один запуск плохо подходит для сравнения небольших фрагментов кода.
Фоновые процессы, кеши и подготовка данных влияют на результат. Модуль timeit помогает повторять операцию и считать длительность серии.
import statistics
import timeit
def build_report():
return sum(number * number for number in range(10_000))
number = 100
single = timeit.timeit(build_report, number=number)
samples = timeit.repeat(build_report, number=number, repeat=5)
per_call = [elapsed / number for elapsed in samples]
print(f"Одна серия: {single:.6f} с")
print(f"Минимум на вызов: {min(per_call):.9f} с")
print(f"Медиана на вызов: {statistics.median(per_call):.9f} с")Вызов timeit.timeit() возвращает суммарное время 100 выполнений. Функция repeat() здесь создает 5 таких серий. Деление на number дает среднюю длительность одного вызова внутри серии.
Минимум помогает оценить выполнение с наименьшими внешними помехами. Медиана характеризует середину набора замеров.
Не смешивайте эти показатели при сравнении двух реализаций.
Короткое выражение можно измерить прямо в терминале:
python -m timeit -r 5 -n 100 "sum(number * number for number in range(10000))"Команда выполнит 5 серий по 100 повторений. В выводе появится время на один цикл с единицей измерения. Параметры и поведение инструмента описывает документация timeit.
- Подготовьте одинаковые входные данные для сравниваемых функций.
- Вынесите подготовку за таймер, если она не входит в задачу.
- Выполните несколько серий с одинаковым числом повторений.
- Сравните минимум или медиану, сохранив версию Python и ОС.
По умолчанию timeit временно отключает сборщик циклического мусора на время замера. Это помогает повторяемости, но может отличаться от условий приложения. Для проверки пользовательских задержек измеряйте также реальный сценарий целиком.
Не привязывайте обычный модульный тест к жесткому порогу времени.
Нагрузка машины способна вызвать случайное падение такого теста. Проверяйте правильность результата отдельно, а производительность сравнивайте в воспроизводимом бенчмарке.
time sleep Python: как задать паузу
Функция time.sleep(seconds) приостанавливает текущий поток на заданное время. Аргумент задает секунды и допускает дробное число. Например, time.sleep(0.5) запрашивает паузу в половину секунды.
Сохраните пример в pause.py и выполните python pause.py:
import time
for attempt in range(1, 4):
print(f"Попытка {attempt}", flush=True)
if attempt < 3:
time.sleep(0.5)
print("Готово")Программа выведет три сообщения с паузами между ними. После последней попытки дополнительной паузы нет.
Реальное ожидание может оказаться длиннее заданного из-за планировщика ОС.
Пауза блокирует только вызывающий поток. Остальные потоки могут продолжать работу. Однако вызов time.sleep() в потоке цикла событий asyncio задерживает другие задачи этого цикла.
В асинхронном коде используйте await asyncio.sleep():
import asyncio
async def main():
for attempt in range(1, 4):
print(f"Попытка {attempt}")
if attempt < 3:
await asyncio.sleep(0.5)
asyncio.run(main())Во время такого ожидания цикл событий может выполнять другие корутины. Функция asyncio.sleep() тоже не гарантирует пробуждение точно в заданный момент.
Наносекундные функции time
В Python 3.7 появились time_ns(), monotonic_ns(), perf_counter_ns() и process_time_ns(). Они возвращают целое число наносекунд вместо секунд типа float. Назначение часов при этом остается прежним.
import time
start = time.perf_counter_ns()
result = sum(range(100_000))
elapsed_ns = time.perf_counter_ns() - start
print("Длительность, нс:", elapsed_ns)
print("Длительность, с:", elapsed_ns / 1_000_000_000)Число float теряет мелкие разряды при больших абсолютных значениях. Целочисленное представление устраняет эту потерю при хранении отметок.
Но суффикс _ns не обещает физическую точность в одну наносекунду.
Вычитайте отметки в целых наносекундах, затем переводите итог в секунды. Для календарных отметок используйте time_ns(), для длительности операции – perf_counter_ns().
Модуль time Python: компоненты времени
Объект struct_time хранит отдельные компоненты даты и времени. Функция gmtime() возвращает их в UTC, а localtime() – в локальном часовом поясе.
import time
stamp = time.time()
utc = time.gmtime(stamp)
local = time.localtime(stamp)
print("gmtime:", utc)
print("\nlocaltime:", local)
print("Месяц:", local.tm_mon)
print("День месяца:", local.tm_mday)
print("Часы:", local.tm_hour)
print("\nmktime:", time.mktime(local))Оба представления относятся к одной исходной отметке stamp. В выводе вы увидите именованные поля struct_time. Обратный слеш в \n создает перевод строки перед подписью.
| Поле | Что хранит |
|---|---|
tm_year | Год |
tm_mon | Месяц от 1 до 12 |
tm_mday | День месяца от 1 до 31 |
tm_hour, tm_min, tm_sec | Часы, минуты, секунды |
tm_wday | День недели: понедельник имеет номер 0 |
tm_yday | Номер дня в году, начиная с 1 |
tm_isdst | Признак летнего времени: 1 – действует, 0 – нет, −1 – неизвестно |
Функция mktime() трактует входные компоненты как локальное время. Не передавайте ей результат gmtime() для обратного преобразования UTC.
Кроме того, struct_time не сохраняет дробную часть исходной секунды.
Работа с часовыми поясами
Изменение часового пояса не изменяет фактическое время – только способ его представления. Функции localtime() и ctime() используют локальные настройки процесса.
Функция time.tzset() доступна только на Unix. В Windows такой функции нет. На Unix она применяет переменную окружения TZ к локальным настройкам времени процесса.
Пример временно включает UTC и затем восстанавливает прежнее окружение:
import os
import time
if hasattr(time, "tzset"):
original_tz = os.environ.get("TZ")
try:
os.environ["TZ"] = "UTC0"
time.tzset()
print("Имена поясов:", time.tzname)
print("Летнее время предусмотрено:", time.daylight)
print("Локальное представление:", time.ctime())
finally:
if original_tz is None:
os.environ.pop("TZ", None)
else:
os.environ["TZ"] = original_tz
time.tzset()
else:
print("Используйте datetime для явного выбора часового пояса")Переменная time.daylight сообщает, предусмотрено ли летнее время локальными правилами. Она не описывает продолжительность светового дня. Для конкретной даты признак летнего времени хранится в tm_isdst.
Не меняйте TZ ради каждого пользователя в многопоточном приложении.
Настройка влияет на процесс целиком. Для прикладного кода используйте datetime с явным часовым поясом.
В Python 3.9 и новее модуль zoneinfo предоставляет именованные пояса. Например, datetime.now(ZoneInfo("Europe/Amsterdam")) получает время с правилами выбранного региона. Для этого импортируйте datetime из datetime и ZoneInfo из zoneinfo.
Модулю нужна база часовых поясов: системная или из пакета tzdata. Если именованные пояса недоступны, установите пакет командой python -m pip install tzdata. Источники данных описывает документация zoneinfo.
Обработка и форматирование времени
Функция strftime() преобразует компоненты времени в строку по шаблону. Функция strptime() разбирает строку по указанному шаблону. Для обычного вывода текущей даты передайте результат localtime().
import time
current = time.localtime()
print("Сейчас:", time.strftime("%Y-%m-%d %H:%M:%S", current))
text = f"{current.tm_year}-08-14 09:30:00"
parsed = time.strptime(text, "%Y-%m-%d %H:%M:%S")
print("\nParsed:", parsed)
print("\nFormatted:", time.strftime("%d.%m.%Y %H:%M", parsed))Первый вывод показывает текущую локальную дату и время. Последний вывод представляет исходную дату в формате «день.месяц.год часы:минуты». Секунды исчезают из строки, поскольку итоговый шаблон их не содержит.
| Директива | Значение |
|---|---|
%Y | Год с веком |
%m | Месяц с ведущим нулем |
%d | День месяца с ведущим нулем |
%H | Часы в 24-часовом формате |
%M | Минуты |
%S | Секунды |
%a | Сокращенное название дня недели |
%b | Сокращенное название месяца |
%j | Номер дня в году из трех цифр |
Названия месяцев и дней недели зависят от текущей локали. Для обмена данными выбирайте числовой формат с явным порядком полей.
Несоответствие строки шаблону при разборе вызывает ValueError.
Основные директивы и платформенные особенности перечисляет справочник strftime. Для дат с часовыми поясами и календарных вычислений удобнее использовать datetime.
Как выбрать таймер под задачу
Начните с границ измеряемой операции. Время функции без печати, выполнение запроса с ожиданием и запуск целого процесса дают разные показатели.
- Если нужна отметка события, сохраняйте
time.time()илиtime.time_ns(). - Для тайм-аута выбирайте
time.monotonic(). - Длительность функции или основного кода скрипта измеряйте через
perf_counter(). - Короткие реализации сравнивайте повторными сериями
timeit. - Затраты процессора оценивайте через
process_time(), отдельного потока – черезthread_time(). - Паузу в синхронном коде задавайте через
time.sleep(), в корутине – черезawait asyncio.sleep().
Совет от нашей редакции: сохраняйте рядом с результатом замера входные данные, число повторений, версию Python и ОС. Без этого разницу между двумя запусками трудно объяснить.
Комментарии
AttributeError: module 'time' has no attribute 'clock'