Как не дублировать код в блоке except

Рейтинг: 4Ответов: 6Опубликовано: 06.08.2025
try:
    pass
except InvalidFileException:
    print('Неверный формат файла')
    input()
    sys.exit()
except FileNotFoundError:
    print('Файл с таким именем не найден')
    input()
    sys.exit()
except ValueError:
    print(f'Ошибка в значении, строка {r}')
    input()
    sys.exit()
except:
    print(f'Ошибка открытия файла. Строка {r}')
    input()
    sys.exit()

Консольное приложение. Вместо pass некий код. После возникновения исключения должна появиться строка, соответствующая этому исключению и после нажатия любой клавиши закрытие программы. Никак не соображу как не дублировать input() и sys.exit().

Ответы

▲ 8

Если у вас появилась функциональность "показать сообщение и умереть", заведите соответствующую функцию и вызывайте везде где необходимо:

def fatal(message):
    print(message)
    input()
    sys.exit()


try:
    pass
except InvalidFileException:
    fatal('Неверный формат файла')
except FileNotFoundError:
    fatal('Файл с таким именем не найден')
except ValueError:
    fatal(f'Ошибка в значении, строка {r}')
except:
    fatal(f'Ошибка открытия файла. Строка {r}')

P.S. Обработка ошибок – не основная функциональность программы. Чем проще и меньше, тем лучше.

▲ 6

Было предложено много вариантов обработки ошибок, но я решил собрать некоторые из идей вместе и немного доработать.

Ключевая мысль — обрабатывать только заранее определённый набор исключений, собранный в кортеж SELECTED_ERRORS. Так мы не перехватываем абсолютно все ошибки, что кажется мне более правильным подходом.

А так же для каждого типа ошибки предусмотрено сообщение — либо статичное, либо с возможностью подставить параметры через lambda. В какой-то мере добавит некой гибкости, что бы избежать захардкоживания словаря.

import sys

class InvalidFileException(Exception):
    pass


ERROR_MSG = {
    FileNotFoundError: "Файл с таким именем не найден.",
    ValueError: lambda r: f"Ошибка в значении, строка: {r}",
    InvalidFileException: "Неверный формат файла.",
}

SELECTED_ERRORS = tuple(ERROR_MSG)  # Для except

try:
    r = "Тест"
    raise ValueError("Invalid number")

except SELECTED_ERRORS as ex:
    handler = ERROR_MSG.get(type(ex))
    
    # Если нет — пробрасываем исключение дальше
    if handler is None:
        raise  # Не ожидаемая ошибка, пусть падает

    msg = handler(r) if callable(handler) else handler
    print(msg)
    input("Нажмите Enter для выхода...")
    sys.exit(1)
▲ 5

Можно использовать словарь:

import sys

class InvalidFileException(Exception):
    pass

try:
    r = 'Тест'

    # тестовый пример
    raise ValueError()

except Exception as ex:
    errors = {
        InvalidFileException: 'Неверный формат файла',
        FileNotFoundError: 'Файл с таким именем не найден',
        ValueError: f'Ошибка в значении, строка {r}',
        Exception: f'Ошибка открытия файла. Строка {r}'
    }
    err = errors.get(ex.__class__, "Неизвестная ошибка")
    print(err)
    input()
    sys.exit()

Вывод:

Ошибка в значении, строка Тест
▲ 2

Если ситуация позволяет, то я бы ввёл переменную, содержащую сообщение об ошибке. Перед заходом в блок try-except "обнуляем" её в None или пустую строку. После выхода проверяем, появилось ли там что-то значимое. Например:

...
err_msg = None
try:
    ...
except InvalidFileException:
    err_msg = 'Неверный формат файла'
except FileNotFoundError:
    err_msg = 'Файл с таким именем не найден'
except ValueError:
    err_msg = f'Ошибка в значении, строка {r}'
...
except Exception as e:
    err_msg = repr(e)

if err_msg:
    print(err_msg, file=sys.stderr)
    input('The application will now close. Press Enter to continue...')
    sys.exit(1)
...
▲ 0

Можно перечислить все исключения сразу если они обрабатываются одинаково

try:
    pass
except (ext1, ext2, ext3) as e:
    # обаботка исключений.
▲ 0

В итоге сделал следующее:

class MixinException:
    def fatal(self):
        print(self.__str__())
        input('Нажать Enter для выхода из программы')
        exit(1)


class MyFileNotFoundError(MixinException, Exception):
    def __str__(self):
        return  'Файл не найден'


class MyValueError(MixinException, Exception):
    def __str__(self):
        return  'Ошибка в значении'


try:
    pass
except FileNotFound:
    raise MyFileNotFoundError().fatal()
except ValueError:
    raise MyValueError().fatal()