Вход на сайт

Просмотр новости

Найдите то, что Вас интересует

Как усыпить Python: полный гид по time.sleep(), asyncio.sleep() и паузам в потоках

Дата публикации: 25-06-2026 19:32:00

Разбираем, как добавлять задержки в Python: от time.sleep() до asyncio.sleep(), Event.wait() и GUI-методов вроде Tkinter.after(). С примерами кода и ловушками.— Читать дальше «Как усыпить Python: полный гид по time.sleep(), asyncio.sleep() и паузам в потоках»

Основное содержимое страницы с новостью.

Иногда Python должен подождать. Задержка между запросами к API, пауза перед повторной проверкой сервера, ритмичный вывод в терминал — за всё это отвечает функция time.sleep(). Она кажется элементарной, но в разных контекстах — синхронном коде, потоках, асинхронности и GUI — пауза устроена по-разному. Разбираем, как не «усыпить» приложение.

Функция time.sleep(seconds) приостанавливает выполнение текущего потока на указанное время. Аргумент — число секунд, включая дробные значения. Например, 0.001 — это одна миллисекунда, а 1.5 — полторы секунды.

			import time

print("Начало")
time.sleep(2.5)
print("Прошло 2,5 секунды")
		

Важный нюанс: time.sleep() гарантирует лишь минимальную задержку. Реальная пауза почти всегда чуть дольше из-за планировщика операционной системы и текущей нагрузки. Для большинства задач это не критично, но для высокоточного тайминга лучше искать другие инструменты.

Типичные сценарии использования

Паузы чаще всего нужны в трёх случаях: чтобы не перегружать внешний сервис, чтобы дать интерфейсу время прогрузиться и чтобы сделать вывод в консоли более читаемым.

  • Распределение запросов к API с ограничением rate limit.
  • Повторные попытки выполнения ненадёжных операций.
  • Пауза между итерациями мониторинга или парсинга.

Мониторинг сайта с интервалом в 60 секунд

Простой аптайм-бот опрашивает страницу и засыпает на минуту. Без задержки скрипт уйдёт в бесконечный цикл и может получить бан по IP.

			import time
import urllib.request
import urllib.error

CHECK_INTERVAL = 60

def uptime_bot(url):
    while True:
        try:
            urllib.request.urlopen(url)
            print(f"{url} доступен")
        except urllib.error.HTTPError as e:
            print(f"HTTP {e.code} для {url}")
        except urllib.error.URLError as e:
            print(f"Ошибка сети: {e.reason} для {url}")
        time.sleep(CHECK_INTERVAL)

if __name__ == "__main__":
    uptime_bot("https://tproger.ru")
		
Совет:
Для реального мониторинга добавьте логирование или уведомления, иначе ошибки останутся только в консоли.

Декоратор для повторных попыток

Ненадёжные операции — загрузка файла, запрос к внешнему API — иногда падают из-за временной проблемы. Вместо того чтобы оборачивать каждый вызов в цикл, удобно сделать декоратор, который повторяет функцию с задержкой.

			import time
from functools import wraps

def retry(delay=3, max_retries=3):
    def decorator(function):
        @wraps(function)
        def wrapper(*args, **kwargs):
            last_exc = None
            for attempt in range(1, max_retries + 1):
                try:
                    return function(*args, **kwargs)
                except Exception as e:
                    last_exc = e
                    print(f"Повтор через {delay} с... ({attempt}/{max_retries})")
                    time.sleep(delay)
            raise last_exc
        return wrapper
    return decorator
		

Обратите внимание на raise внутри блока except: если его убрать, исключение не пойдёт наружу, и декоратор не поймёт, что нужна повторная попытка.

			import urllib.request
import urllib.error
from utils import retry

@retry(delay=2)
def download_file(url):
    response = urllib.request.urlopen(url)
    print(f"Скачано {url} ({response.length} байт)")

download_file("https://example.com/data.csv")
		

Паузы в потоках: Event.wait()

В потоках можно использовать time.sleep(), но он непрерываен: поток не сможет быстро завершиться, пока спит. Для корректной остановки лучше применять threading.Event().wait(). Этот метод прерывается, как только событие установлено через event.set().

			import logging
import threading

WORKER_INTERVAL = 1

def worker(event):
    while not event.is_set():
        logging.debug("Рабочий поток на связи")
        event.wait(WORKER_INTERVAL)

def main():
    logging.basicConfig(
        level=logging.DEBUG,
        format="{relativeCreated:>6,.0f} ms | {threadName:<18} | {message}",
        style="{",
    )
    event = threading.Event()
    thread = threading.Thread(target=worker, args=(event,))
    thread.start()
    try:
        while not event.is_set():
            logging.debug("Главный поток на связи")
            event.wait(0.75)
    except KeyboardInterrupt:
        event.set()

if __name__ == "__main__":
    main()
		

Такой подход позволяет аккуратно завершить все потоки по Ctrl+C: event.set() мгновенно будит все ожидающие wait().

Неблокирующие паузы в asyncio

Асинхронный код в Python появился в версии 3.4 модуля asyncio и получил синтаксис async/await в 3.5. Внутри корутин нельзя использовать обычный time.sleep(): он заморозит весь event loop. Для паузы в асинхронном коде есть asyncio.sleep().

			import asyncio

async def main():
    print("Привет...")
    await asyncio.sleep(1)
    print("...мир!")

asyncio.run(main())
		

Ключевое отличие: asyncio.sleep() приостанавливает только текущую корутину, уступая управление event loop. Остальные задачи продолжают выполняться. Это особенно важно при соблюдении rate limit при параллельных запросах.

			import asyncio
import aiohttp

RATE_LIMIT_DELAY = 1

async def fetch_page(session, url):
    async with session.get(url) as response:
        print(f"{url} ({response.status})")
        await asyncio.sleep(RATE_LIMIT_DELAY)

async def main():
    urls = [
        "https://httpbin.org/get",
        "https://httpbin.org/ip",
        "https://httpbin.org/headers",
    ]
    async with aiohttp.ClientSession() as session:
        for url in urls:
            await fetch_page(session, url)

asyncio.run(main())
		

Как не заморозить GUI

В GUI-фреймворках весь интерфейс работает в главном потоке с собственным циклом событий. Если вызвать time.sleep() в обработчике кнопки, окно повиснет: не будет отрисовки, не сработают клики, а в Windows может появиться предупреждение о неответствии.

			import tkinter

DELAY = 3000  # миллисекунды

def on_click():
    root.after(DELAY, lambda: print("Готово!"))

root = tkinter.Tk()
root.geometry("400x400")
button = tkinter.Button(text="Нажми меня", command=on_click)
button.pack()
root.mainloop()
		

Метод .after() в Tkinter планирует callback через заданное число миллисекунд и сразу возвращает управление циклу событий. Аналог в wxPython — wx.CallLater(). Паттерн универсален: не блокируйте поток, планируйте отложенный вызов.

  • time.sleep() — универсальный способ поставить синхронную паузу, но он блокирует поток целиком.
  • Для повторных попыток удобен декоратор с задержкой, который ловит исключения и делает retry.
  • В потоках предпочитайте Event.wait(): его можно прервать через event.set().
  • В асинхронном коде используйте asyncio.sleep(), иначе заморозите весь event loop.
  • В GUI применяйте фреймворковые методы вроде Tkinter.after(), чтобы интерфейс оставался отзывчивым.

Часто задаваемые вопросы

1

Как сделать паузу в одну секунду?

Импортируйте модуль time и вызовите time.sleep(1). Выполнение текущего потока приостановится на одну секунду.

2

Можно ли задать задержку в миллисекундах?

Да, передав дробное число: time.sleep(0.5) — 500 мс, time.sleep(0.001) — 1 мс.

3

В чём разница между time.sleep() и asyncio.sleep()?

time.sleep() блокирует весь поток, а asyncio.sleep() только текущую корутину, позволяя event loop запускать другие задачи.

4

Почему GUI зависает при использовании time.sleep()?

Потому что GUI обрабатывает события и отрисовку в главном потоке. time.sleep() его блокирует, поэтому нужны фреймворковые методы отложенного вызова.

5

Что использовать в потоках: time.sleep() или Event.wait()?

Лучше Event.wait(), потому что его можно прервать для корректной остановки потока.

Выводы

Пауза в коде — это не просто «подождать секунду». В синхронном скрипте достаточно time.sleep(), в потоке важно уметь выходить по сигналу, в асинхронном коде нельзя блокировать event loop, а в GUI нужно работать в рамках фреймворкового цикла событий. Правильный инструмент зависит от контекста, и выбор влияет на отзывчивость и стабильность приложения.

Не блокируйте поток без причины. Если можно уступить управление — уступите.

Редакция TprogerTproger

Источник и дополнительные материалы: Real Python — Python sleep(): How to Add Time Delays to Your Code.

Схожие новости

#Наименование новостиТональностьИнформативностьДата публикации
1Async Rust: как уменьшить бинарник, пока rustc не оптимизирован0729-06-2026
2Аварийное восстановление до аварии: как настроить DRaaS, пока ничего не упал5802-07-2026
3Как выбрать VPS/VDS под свой проект: гайд по параметрам и 6 провайдеров0830-06-2026
4Кнопка «наверх» в Django: почему в проде это уже не три строки JavaScript0701-07-2026
5Как оживить фото нейросетью бесплатно: пошаговый гайд 2026 года5703-07-2026
6Как ограничить расходы на OpenAI API, чтобы ИИ-агенты не сожгли бюджет0804-07-2026
7Как написать отчёт по практике с помощью ИИ и готовых промптов?5702-07-2026
8Git в Telegram: как я избавился от JSON, победил Markdown и получил security by design5702-07-2026
9Зарубежный хостинг для сайта: ТОП-25 иностранных хостинг-провайдеров0526-06-2026

Классификация: Мнения. Схожих патентов: 0. Схожих новостей: 9. Тональность: 0. Информативность: 7. Источник: tproger.ru.