Как часто пользовательские исключения определяются в python?

При попытке устранить потенциальное состояние гонки в модуле python, который я написал для мониторинга некоторых специализированных рабочих процессов, я узнал о стиле кодирования python «проще просить, чем разрешение» (EAFP), и теперь я собираю множество пользовательских исключений с помощью try / кроме блоков, где я использовал, если / thens.

Я новичок в python, и этот стиль EAFP имеет смысл логически и, похоже, делает мой код более надежным, но что-то об этом чувствует себя за бортом. Является ли плохая практика определять одно или несколько исключений для каждого метода?

Эти пользовательские исключения, как правило, полезны только для одного метода, и, хотя он выглядит как функционально правильное решение, кажется, что много кода для поддержания.

Здесь примерный метод, например:

class UploadTimeoutFileMissing(Exception): def __init__(self, value): self.parameter = value def __str__(self): return repr(self.parameter) class UploadTimeoutTooSlow(Exception): def __init__(self, value): self.parameter = value def __str__(self): return repr(self.parameter) def check_upload(file, timeout_seconds, max_age_seconds, min_age_seconds): timeout = time.time() + timeout_seconds ## Check until file found or timeout while (time.time() < timeout): time.sleep(5) try: filetime = os.path.getmtime(file) filesize = os.path.getsize(file) except OSError: print "File not found %s" % file continue fileage = time.time() - filetime ## Make sure file isn't pre-existing if fileage > max_age_seconds: print "File too old %s" % file continue ## Make sure file isn't still uploading elif fileage <= min_age_seconds: print "File too new %s" % file continue return(filetime, filesize) ## Timeout try: filetime filesize raise UploadTimeoutTooSlow("File still uploading") except NameError: raise UploadTimeoutFileMissing("File not sent") 

5 Solutions collect form web for “Как часто пользовательские исключения определяются в python?”

определить одно или несколько исключений для каждого метода

Если вы имеете в виду, что исключение фактически определено для каждого метода, как в «внутри тела метода», то да . Это плохая практика. Это также верно, если вы определяете два исключения, которые относятся к одной и той же ошибке, но вы создаете два, потому что два разных метода их повышают.

Если вы спросите, является ли неправильная практика поднимать более одного исключения по методу, то нет , это хорошая практика. И если ошибки не относятся к одной категории, вполне нормально определять несколько исключений для каждого модуля.

В общем, для более крупных модулей вы будете определять более одного исключения. Если бы вы работали над некоторой арифметической библиотекой, и вы бы определили ZeroDivisionError и OverflowError (если они еще не были определены в python, потому что вы, конечно, можете повторно использовать их), это было бы прекрасно.

Является ли плохая практика определять одно или несколько исключений для каждого метода?

Да.

Один из них более типичен. Это зависит, конечно, от детальной семантики. Вопрос сводится к следующему: «Что вы действительно попытаетесь поймать?»

Если вы никогда не собираетесь использовать except ThisVeryDetailedException: в вашем коде, ваше очень подробное исключение не очень полезно.

Если вы можете это сделать: except Error as e: if e.some_special_case течение очень немногих раз имеет значение, то вы можете легко упростить одно исключение на модуль и обрабатывать ваши особые случаи как атрибуты исключения, а не различные типы исключений.

Общие предложения (по одному на модуль с именем Error ) означают, что ваш код будет часто выглядеть так.

 try: something except some_module.Error as e: carry on 

Это дает вам хорошее соглашение об именах: module.Error . Это охватывает множество грехов.


На несвязанной ноте, если вы считаете, что у вас есть «потенциальное состояние гонки», вы должны, вероятно, правильно перепроектировать или прекратить попытки использовать потоки или переключиться на многопроцессорность. Если вы используете многопроцессорную обработку, вы обнаружите, что очень легко избежать условий гонки.

Я собираюсь взвесить это, потому что необычные исключения дороги моему сердцу. Я объясню свои обстоятельства, и читатель может взвесить их против своих.

Я архитектор конвейера для компании с визуальными эффектами – большая часть того, что я делаю, связана с разработкой того, что я называю «API-интерфейс Facility» – это система из большого количества модулей, которые обрабатывают все, от поиска вещей в файловой системе, управления модулем / инструментом / project, для обработки типов данных из различных приложений CG для обеспечения совместной работы.

Я изо всех сил стараюсь, чтобы встроенные исключения Python никогда не возникали. Поскольку наши разработчики будут полагаться на экосистему существующих модулей, чтобы создавать свои собственные инструменты, API API позволяет общему побегу IOError быть контрпродуктивным – тем более, что вызывающая подпрограмма может даже не знать, что она читает файловую систему (абстракция красивая вещь). Если базовый модуль не может выразить что-то значимое в этой ошибке, необходимо выполнить большую работу.

Мой подход к решению этого заключается в создании класса исключения объекта, из которого выводятся все другие исключения объекта. Существуют подклассы этого для конкретных типов задач или конкретных хост-приложений, что позволяет мне настраивать обработку ошибок (например, исключения, поднятые в Maya, запустит пользовательский интерфейс, помогающий устранить неполадки, поскольку обычное исключение будет поднято в незаметной консоли и часто будут упущены).

Всевозможные отчеты встроены в класс исключения объекта – исключения не отображаются для пользователя, также не сообщаются внутренне. Для ряда исключений я получаю IM в любое время, когда его поднимают. Другие просто тихо сообщают в базу данных, в которой я могу запрашивать последние (ежедневные или еженедельные) отчеты. Каждая ссылка на EXTENSIVE данные, полученные из сеанса пользователя, обычно включает скриншот, трассировку стека, конфигурацию системы и многое другое. Это означает, что я могу эффективно устранять проблемы до того, как они сообщаются, – и у вас больше информации на кончиках пальцев, чем большинство пользователей, которые могут предоставить.

Очень прекрасные градации в назначении обескуражены – исключения принимают переданные значения (иногда даже словарь вместо строки, если мы хотим предоставить много данных для устранения неполадок), чтобы обеспечить их форматированный вывод.

Поэтому нет – я не думаю, что определение исключения или два в модуле необоснованно, но они должны быть значимыми и добавлять что-то в проект. Если вы просто обертываете raise MyIOError("I got an IO error!") чтобы raise MyIOError("I got an IO error!") , Тогда вы можете захотеть переосмыслить это.

Ваш вопрос слишком широк, чтобы получить целевой ответ. В общем, EAFP – это Pythonic. На практике, однако, легко переусердствовать. Например, я читаю ваш:

и теперь я собираю множество пользовательских исключений с помощью try / except блоков, где я использовал if / thens.

И это меня беспокоит. Исключения предназначены только для исключительных ситуаций, а не для замены потока управления. В большинстве случаев замена условия на исключение является неуместной.

Не могли бы вы предоставить более конкретную выборку одного метода, в котором вы добавили исключения, и класс исключений, который вы определили для этой цели?

Я не думаю, что для каждого возможного сценария необходимо иметь исключительно конкретное исключение. Один UploadTimeoutError , вероятно, будет прекрасен, и вы можете просто настроить строку исключений – в конце концов, это строки. Обратите внимание, что у python нет отдельного исключения для каждого возможного типа синтаксической ошибки, а всего лишь для SyntaxError .

Также – действительно ли необходимо определить методы __init__ и __str__ для каждого из ваших пользовательских исключений? Насколько я могу судить, если вы не выполняете какое-либо необычное поведение, вам не нужно добавлять код:

 >>> class MyException(Exception): pass ... >>> raise MyException("oops!") Traceback (most recent call last): File "<ipython console>", line 1, in <module> MyException: oops! >>> str(MyException("oops!")) 'oops!' 
  • python: подсчет количества гласных или согласных во входном слове пользователя
  • Как фильтровать список словарей с соответствующими значениями для заданного ключа
  • Сравнение списков в Python
  • Автоматическое изменение раскладки клавиатуры в WinXP
  • Можно ли создать таблицу / схему BigQuery без заполнения данными?
  • поток файлов python ftp или многопроцессорный
  • Как я могу определить, какая другая копия скрипта Python уже запущена
  • Возврат продукта из списка
  • чтение файлов как по вертикальным спискам, так и по горизонтальным спискам (python 3.2)
  • Каковы плюсы и минусы различных реализаций Python?
  • Загрузка общедоступных файлов на Google Диске (Python)
  • Python - лучший язык программирования в мире.