Разбираем, как добавлять задержки в 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() гарантирует лишь минимальную задержку. Реальная пауза почти всегда чуть дольше из-за планировщика операционной системы и текущей нагрузки. Для большинства задач это не критично, но для высокоточного тайминга лучше искать другие инструменты.
Паузы чаще всего нужны в трёх случаях: чтобы не перегружать внешний сервис, чтобы дать интерфейсу время прогрузиться и чтобы сделать вывод в консоли более читаемым.
Простой аптайм-бот опрашивает страницу и засыпает на минуту. Без задержки скрипт уйдёт в бесконечный цикл и может получить бан по 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")
В потоках можно использовать 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().
Асинхронный код в 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-фреймворках весь интерфейс работает в главном потоке с собственным циклом событий. Если вызвать 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() — универсальный способ поставить синхронную паузу, но он блокирует поток целиком.Event.wait(): его можно прервать через event.set().asyncio.sleep(), иначе заморозите весь event loop.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.
| # | Наименование новости | Тональность | Информативность | Дата публикации |
|---|---|---|---|---|
| 1 | Async Rust: как уменьшить бинарник, пока rustc не оптимизирован | 0 | 7 | 29-06-2026 |
| 2 | Аварийное восстановление до аварии: как настроить DRaaS, пока ничего не упал | 5 | 8 | 02-07-2026 |
| 3 | Как выбрать VPS/VDS под свой проект: гайд по параметрам и 6 провайдеров | 0 | 8 | 30-06-2026 |
| 4 | Кнопка «наверх» в Django: почему в проде это уже не три строки JavaScript | 0 | 7 | 01-07-2026 |
| 5 | Как оживить фото нейросетью бесплатно: пошаговый гайд 2026 года | 5 | 7 | 03-07-2026 |
| 6 | Как ограничить расходы на OpenAI API, чтобы ИИ-агенты не сожгли бюджет | 0 | 8 | 04-07-2026 |
| 7 | Как написать отчёт по практике с помощью ИИ и готовых промптов? | 5 | 7 | 02-07-2026 |
| 8 | Git в Telegram: как я избавился от JSON, победил Markdown и получил security by design | 5 | 7 | 02-07-2026 |
| 9 | Зарубежный хостинг для сайта: ТОП-25 иностранных хостинг-провайдеров | 0 | 5 | 26-06-2026 |