Как не дублировать код в блоке except
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().
Ответы (6 шт):
Можно перечислить все исключения сразу если они обрабатываются одинаково
try:
pass
except (ext1, ext2, ext3) as e:
# обаботка исключений.
Если ситуация позволяет, то я бы ввёл переменную, содержащую сообщение об ошибке. Перед заходом в блок 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)
...
Можно использовать словарь:
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()
Вывод:
Ошибка в значении, строка Тест
Если у вас появилась функциональность "показать сообщение и умереть", заведите соответствующую функцию и вызывайте везде где необходимо:
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. Обработка ошибок – не основная функциональность программы. Чем проще и меньше, тем лучше.
Было предложено много вариантов обработки ошибок, но я решил собрать некоторые из идей вместе и немного доработать.
Ключевая мысль — обрабатывать только заранее определённый набор исключений, собранный в кортеж 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)
В итоге сделал следующее:
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()