Подтвердить что ты не робот

Какое исключение я должен поднимать по неправильным/незаконным комбинациям аргументов в Python?

Мне было интересно узнать о лучших методах указания неверных комбинаций аргументов в Python. Я столкнулся с несколькими ситуациями, когда у вас есть такая функция:

def import_to_orm(name, save=False, recurse=False):
    """
    :param name: Name of some external entity to import.
    :param save: Save the ORM object before returning.
    :param recurse: Attempt to import associated objects as well. Because you
        need the original object to have a key to relate to, save must be
        `True` for recurse to be `True`.
    :raise BadValueError: If `recurse and not save`.
    :return: The ORM object.
    """
    pass

Единственное раздражение заключается в том, что каждый пакет имеет свой собственный, обычно немного отличающийся BadValueError. Я знаю, что в Java существует java.lang.IllegalArgumentException - хорошо ли понятно, что каждый будет создавать свой собственный BadValueError в Python или есть другой предпочтительный метод?

4b9b3361

Ответ 1

Я просто подниму ValueError, если вам не требуется более конкретное исключение.

def import_to_orm(name, save=False, recurse=False):
    if recurse and not save:
        raise ValueError("save must be True if recurse is True")

Нет смысла делать class BadValueError(ValueError):pass - ваш пользовательский класс идентичен при использовании ValueError, так почему бы не использовать это?

Ответ 2

Я бы наследовал от ValueError

class IllegalArgumentError(ValueError):
    pass

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

Если вам нужно поймать эту конкретную ошибку, полезно иметь имя.

Ответ 3

Я думаю, что лучший способ справиться с этим - это то, как сам Python справляется с этим. Python вызывает ошибку TypeError. Например:

$ python -c 'print(sum())'
Traceback (most recent call last):
File "<string>", line 1, in <module>
TypeError: sum expected at least 1 arguments, got 0

Наш младший разработчик только что нашел эту страницу в поиске Google для "неправильных аргументов исключения Python", и я удивлен, что очевидный (для меня) ответ никогда не предлагался в течение десятилетия, так как этот вопрос был задан.

Ответ 4

В основном я видел встроенный ValueError, используемый в этой ситуации.

Ответ 5

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

Поднят при выполнении встроенной операции или функция получает аргумент, который имеет правильный тип, но неулокальный ценности, а ситуация не описывается более точным исключением таких как IndexError.

- Документация ValueError

Ответ 6

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

class BadCallError(ValueError):
    pass

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

Не должно ли это быть стандартным исключением в Python?

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

Ответ 7

Это зависит от того, в чем проблема с аргументами.

Если аргумент имеет неправильный тип, вызовите TypeError. Например, когда вы получаете строку вместо одного из этих логических значений.

if not isinstance(save, bool):
    raise TypeError(f"Argument save must be of type bool, not {type(save)}")

Однако обратите внимание, что в Python мы редко делаем какие-либо проверки, подобные этой. Если аргумент действительно недействителен, более глубокая функция, вероятно, сделает жалобу за нас. И если мы проверим только логическое значение, возможно, какой-то пользователь кода позже просто передаст ему строку, зная, что непустые строки всегда равны True. Это может спасти его.

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

if recurse and not save:
    raise ValueError("If recurse is True, save should be True too")

Или в этом конкретном случае истинное значение recurse подразумевает истинное значение save. Поскольку я считаю, что это восстановление после ошибки, вы также можете пожаловаться в журнале.

if recurse and not save:
    logging.warning("Bad arguments in import_to_orm() - if recurse is True, so should save be")
    save = True