Исключение FileNotFoundError: методы предотвращения и отлова в скриптах
Надёжный способ: комбинация проверки и обработки исключений
Наиболее устойчивым решением считается сочетание проверки существования файла с помощью os.path.exists() или Path.exists() и последующей обработки исключения FileNotFoundError в блоке try-except. Этот подход позволяет избежать состояния гонки (race condition), когда файл может быть удалён между проверкой и открытием.
import os
filepath = 'data.txt'
try:
if os.path.exists(filepath):
with open(filepath, 'r') as f:
content = f.read()
else:
raise FileNotFoundError(f"Файл {filepath} не найден")
except FileNotFoundError as e:
print(f"Ошибка: {e}")Client error python (ошибка http-клиента в python)
Вместо os.path.exists() можно использовать pathlib.Path.exists(), что более современно:
from pathlib import Path
path = Path('data.txt')
try:
if path.exists():
with path.open('r') as f:
content = f.read()
else:
raise FileNotFoundError(f"Файл {path} не найден")
except FileNotFoundError as e:
print(f"Ошибка: {e}")No installed python found (python не найден в системе)
Возможные проблемы
- Race condition – даже двойная проверка не гарантирует доступность файла, если между проверкой и открытием происходит удаление. В таких случаях единственный выход – обработка исключения.
- Права доступа – файл может существовать, но быть недоступным для чтения. Это вызовет PermissionError, который тоже стоит обрабатывать.
- Неверный путь – относительные пути зависят от рабочего каталога. Рекомендуется использовать абсолютные пути или os.path.join().
Как просто отловить ошибку без предварительной проверки?
Самый распространённый вариант – поймать исключение FileNotFoundError при попытке открыть файл. Это уместно, когда файл должен существовать, и его отсутствие является исключительной ситуацией.
try:
with open('config.json', 'r') as f:
data = json.load(f)
except FileNotFoundError:
print('Файл конфигурации не найден. Используются настройки по умолчанию.')
Python traceback using (трассировка ошибок в python)
Типичная ошибка
Забывают указать кодировку при открытии текстового файла. Если файл в UTF-8, но содержит символы, не входящие в ASCII, возможно исключение UnicodeDecodeError. Добавление параметра encoding='utf-8' решает проблему.
Что делать, если файл может отсутствовать, но его нужно создать?
Для записи данных полезно создавать файл автоматически. Режим 'w' создаёт файл, если его нет, а 'x' – только если его не существует (иначе вызовет FileExistsError).
try:
with open('output.txt', 'w') as f:
f.write('Новые данные')
except OSError as e:
print(f'Не удалось создать файл: {e}')Python pip not found (ошибка 'pip not found' в python)
Для создания вложенных директорий применяется os.makedirs() с параметром exist_ok=True.
from pathlib import Path
path = Path('logs/app.log')
path.parent.mkdir(parents=True, exist_ok=True)
with path.open('a') as f:
f.write('Запись лога\n')Unable to locate package python (ошибка 'unable to locate package' в python)
Проблема
Если файл уже существует и используется режим 'w', его содержимое будет стёрто. Для добавления следует использовать 'a'.
Как игнорировать отсутствие файла и продолжить выполнение?
Иногда нужно молча пропустить несуществующий файл, например, при чтении опционального конфигурационного файла. Для этого можно использовать contextlib.suppress или пустой блок except.
from contextlib import suppress
with suppress(FileNotFoundError):
with open('optional.txt', 'r') as f:
data = f.read()File not found python (ошибка filenotfounderror в python)
Осторожно
Подавление исключения без логирования может затруднить отладку. Рекомендуется хотя бы записывать событие в лог.
Как обрабатывать ошибку при поиске файла в нескольких директориях?
Приложение может искать файл в списке путей. Помогает цикл по директориям с проверкой существования.
from pathlib import Path
search_paths = ['/etc/app', '/usr/local/etc/app', os.getcwd()]
config = None
for base in search_paths:
path = Path(base) / 'config.ini'
if path.exists():
with path.open() as f:
config = f.read()
break
if config is None:
raise FileNotFoundError('Конфигурационный файл не найден ни в одной из директорий')Проблема
При множестве поисков может страдать производительность. Для больших списков путей стоит кэшировать результаты проверки.
Расширенные примеры обработки FileNotFoundError
Пример 1: рекурсивный поиск файла по маске
from pathlib import Path
def find_first_file(pattern, root='.'):
root_path = Path(root)
for path in root_path.rglob(pattern):
if path.is_file():
return path
raise FileNotFoundError(f'Файл с шаблоном {pattern} не найден в {root}')
try:
found = find_first_file('*.txt')
print(f'Найден файл: {found}')
except FileNotFoundError as e:
print(e)Найден файл: /home/user/data/example.txt
Этот код ищет первый текстовый файл во всех поддиректориях. Если ничего не найдено, возбуждается FileNotFoundError с описанием.
Пример 2: чтение нескольких файлов с обработкой ошибок
files = ['data1.csv', 'data2.csv', 'data3.csv']
contents = []
for fname in files:
try:
with open(fname, 'r') as f:
contents.append(f.read())
except FileNotFoundError:
print(f'Пропущен отсутствующий файл: {fname}')
except PermissionError:
print(f'Нет прав на чтение файла: {fname}')
finally:
print(f'Обработка файла {fname} завершена')Пропущен отсутствующий файл: data1.csv Обработка файла data1.csv завершена Обработка файла data2.csv завершена Обработка файла data3.csv завершена
Показана обработка разных ошибок и обязательное выполнение блока finally.
Пример 3: работа с временными файлами (tempfile)
import tempfile
import os
tmp = tempfile.NamedTemporaryFile(delete=False)
tmp.write(b'временные данные')
print(f'Создан временный файл: {tmp.name}')
tmp.close()
# Попытка открыть после удаления
os.unlink(tmp.name)
try:
with open(tmp.name, 'r') as f:
print(f.read())
except FileNotFoundError:
print('Файл был удалён, ошибка перехвачена')Создан временный файл: /tmp/tmpxyz123 Файл был удалён, ошибка перехвачена
Демонстрируется, как обрабатывать FileNotFoundError при работе с временными файлами, которые могут быть удалены программно.
Пример 4: использование пользовательского исключения для уточнения ошибки
class ConfigNotFoundError(FileNotFoundError):
pass
def load_config(path):
if not Path(path).exists():
raise ConfigNotFoundError(f'Конфигурация не найдена: {path}')
return Path(path).read_text()
try:
config = load_config('/etc/myapp/config.ini')
except ConfigNotFoundError as e:
print(f'Специфическая ошибка: {e}')
except FileNotFoundError as e:
print(f'Общая ошибка файла: {e}')Специфическая ошибка: Конфигурация не найдена: /etc/myapp/config.ini
Такой подход позволяет точнее классифицировать ошибку и обрабатывать её по-разному.
Пример 5: асинхронное чтение с обработкой FileNotFoundError
import asyncio
import aiofiles
async def read_safe(path):
try:
async with aiofiles.open(path, 'r') as f:
return await f.read()
except FileNotFoundError:
return None
async def main():
content = await read_safe('missing.txt')
if content is None:
print('Файл не найден, возвращён None')
else:
print(content)
asyncio.run(main())Файл не найден, возвращён None
Пример для асинхронного ввода-вывода с библиотекой aiofiles.