Как дождаться файла в Python: циклы и таймеры
Ожидание появления файла в Python
Основной эффективный подход: цикл с проверкой и паузой
Наиболее распространённое решение для ожидания файла - это цикл while not os.path.exists() с вызовом time.sleep(). Такой подход снижает нагрузку на процессор за счёт пауз между проверками. Он подходит для сценариев, где время появления файла не критично, а задержка в несколько секунд допустима.
import os
import time
file_path = "data.txt"
while not os.path.exists(file_path):
time.sleep(2) # пауза 2 секунды
print("Файл найден:", file_path)ввод программ на python (ввод данных в программе python)
В этом коде программа ожидает появления файла data.txt, проверяя его наличие каждые 2 секунды. После обнаружения выполняется вывод сообщения.
Типичные проблемы и их решения:
- Без
time.sleep()цикл будет потреблять 100% CPU. Решение: всегда добавлять паузу. - Файл может появиться и сразу исчезнуть (например, временный файл). Решение: после обнаружения дополнительно проверить
os.path.isfile()и, возможно, дождаться стабильности размера. - Отсутствие прав на чтение родительской директории -
os.path.exists()вернётFalse. Решение: проверять права доступа.
Как выполнять ожидание появления файла с периодической проверкой?
Самый простой вариант - бесконечный цикл с проверкой и паузой. Он не требует дополнительных библиотек.
import os, time
path = "result.dat"
while True:
if os.path.exists(path):
break
time.sleep(1)Python file io (ввод-вывод файлов в python)
Цель: простейшее ожидание без таймаута. Используется в скриптах, работающих в фоне до завершения внешнего процесса.
Если внешний процесс никогда не создаст файл, программа зависнет. Рекомендуется всегда добавлять таймаут.
Как ограничить время ожидания файла?
Добавление счётчика или time.time() позволяет выйти из цикла по истечении заданного времени.
import os, time
file_path = "report.csv"
timeout = 30 # секунд
start = time.time()
while not os.path.exists(file_path):
if time.time() - start > timeout:
print("Таймаут ожидания файла")
break
time.sleep(1)
else:
print("Файл появился вовремя")
Python temp files (временные файлы в python)
Цель: предотвращение зависания программы. Подходит для задач с жёсткими временными рамками.
При превышении таймаута нужно корректно обработать ситуацию (например, повторная попытка или запись в лог).
Как ожидать файл с помощью модуля pathlib?
Современная альтернатива - pathlib.Path.exists(). Код становится более читаемым.
from pathlib import Path
import time
file = Path("config.json")
while not file.exists():
time.sleep(0.5)
print("Конфигурация загружена")Python index files (индексация файлов в python)
Цель: использование объектно-ориентированного подхода. Удобно при работе с множеством путей.
Метод exists() возвращает True и для директорий. Если нужно ждать именно файл, используйте file.is_file().
Как эффективно отслеживать появление файла без постоянной проверки?
Библиотека watchdog позволяет подписаться на события файловой системы (создание, изменение, удаление). Это снижает нагрузку и даёт мгновенную реакцию.
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
import time
class MyHandler(FileSystemEventHandler):
def on_created(self, event):
if not event.is_directory and event.src_path.endswith(".dat"):
print(f"Файл создан: {event.src_path}")
observer.stop()
observer = Observer()
observer.schedule(MyHandler(), path=".", recursive=False)
observer.start()
try:
while observer.is_alive():
observer.join(1)
except KeyboardInterrupt:
observer.stop()
observer.join()File python class (класс для работы с файлами в python)
Цель: реакция на появление файла в реальном времени. Используется в системах мониторинга, обработки очередей.
Требуется установка pip install watchdog. На некоторых платформах (Windows, macOS) работают разные наблюдатели - могут потребоваться дополнительные настройки.
Как убедиться, что появился именно файл, а не папка?
Использование os.path.isfile() или Path.is_file() гарантирует, что объект является файлом, а не директорией или ссылкой.
import os, time
path = "data"
while not os.path.isfile(path):
time.sleep(1)
print("Это файл")
Цель: избежать ложного срабатывания при появлении папки с таким же именем. Важно, если ожидается строго файл.
Даже если файл существует, он может быть заблокирован другим процессом. Рекомендуется дополнительно пробовать его открыть с обработкой исключений.
Расширенные примеры ожидания файла
# Пример 1: Ожидание с проверкой типа и размера файла
import os, time
path = "upload.zip"
min_size = 1024 # минимум 1 КБ
while True:
if os.path.isfile(path):
size = os.path.getsize(path)
if size >= min_size:
print(f"Файл готов, размер: {size} байт")
break
else:
print(f"Файл ещё мал ({size} байт), ждём...")
time.sleep(2)
Файл ещё мал (512 байт), ждём... Файл готов, размер: 2048 байт
В этом примере программа ожидает не только появления файла, но и его минимального размера, что полезно при дописывании данных.
# Пример 2: Использование threading.Event для сигнализации
import os, time, threading
event = threading.Event()
def waiter():
while not os.path.exists("signal.txt"):
time.sleep(0.5)
event.set()
thread = threading.Thread(target=waiter)
thread.start()
event.wait(timeout=10)
if event.is_set():
print("Файл появился, продолжаем")
else:
print("Таймаут, файл не обнаружен")
Файл появился, продолжаем
Здесь ожидание вынесено в отдельный поток. Основной поток может выполнять другие задачи, а потом дождаться сигнала через Event.
# Пример 3: watchdog с фильтром по маске
from watchdog.observers import Observer
from watchdog.events import PatternMatchingEventHandler
import time
class MyHandler(PatternMatchingEventHandler):
def on_created(self, event):
print(f"Создан: {event.src_path}")
self.observer.stop()
handler = MyHandler(patterns=["*.csv", "*.tsv"])
observer = Observer()
handler.observer = observer
observer.schedule(handler, path="/input", recursive=False)
observer.start()
try:
while observer.is_alive():
observer.join(1)
except KeyboardInterrupt:
observer.stop()
observer.join()
Создан: /input/data.csv
Вариант с PatternMatchingEventHandler позволяет ожидать только файлы определённых расширений, игнорируя остальные.
# Пример 4: Кастомный декоратор для повторных попыток
import os, time, functools
def wait_file(path, timeout=60, interval=1):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
while not os.path.exists(path):
if time.time() - start > timeout:
raise TimeoutError(f"Файл {path} не появился за {timeout} сек.")
time.sleep(interval)
return func(*args, **kwargs)
return wrapper
return decorator
@wait_file("output.log", timeout=30)
def process_log():
print("Файл готов, начинаем обработку")
process_log()
Файл готов, начинаем обработку
Декоратор позволяет компактно добавить ожидание файла к любой функции, сохраняя читаемость кода.
# Пример 5: Использование inotify (Linux) через pyinotify
import pyinotify
import os
wm = pyinotify.WatchManager()
mask = pyinotify.IN_CREATE | pyinotify.IN_OPEN
class EventHandler(pyinotify.ProcessEvent):
def process_IN_CREATE(self, event):
if event.name == "config.yaml":
print("Файл config.yaml создан")
wm.stop()
handler = EventHandler()
notifier = pyinotify.Notifier(wm, handler)
wm.add_watch("/etc", mask, rec=False)
notifier.loop()
Файл config.yaml создан
Для Linux доступен прямой мониторинг через inotify (библиотека pyinotify). Это ещё более производительно, чем watchdog, так как работает на уровне ядра.