Каковы недостатки возврата экземпляра Exception вместо его вызова в Python? - PullRequest
3 голосов
/ 22 января 2010

Я немного поработал с python-couchdb и desktopcouch. В одном из представленных мной патчей я обернул функцию db.update из couchdb. Для тех, кто не знаком с python-couchdb, эта функция выглядит следующим образом:

def update(self, documents, **options):
    """Perform a bulk update or insertion of the given documents using a
    single HTTP request.

    >>> server = Server('http://localhost:5984/')
    >>> db = server.create('python-tests')
    >>> for doc in db.update([
    ...     Document(type='Person', name='John Doe'),
    ...     Document(type='Person', name='Mary Jane'),
    ...     Document(type='City', name='Gotham City')
    ... ]):
    ...     print repr(doc) #doctest: +ELLIPSIS
    (True, '...', '...')
    (True, '...', '...')
    (True, '...', '...')

    >>> del server['python-tests']

    The return value of this method is a list containing a tuple for every
    element in the `documents` sequence. Each tuple is of the form
    ``(success, docid, rev_or_exc)``, where ``success`` is a boolean
    indicating whether the update succeeded, ``docid`` is the ID of the
    document, and ``rev_or_exc`` is either the new document revision, or
    an exception instance (e.g. `ResourceConflict`) if the update failed.

    If an object in the documents list is not a dictionary, this method
    looks for an ``items()`` method that can be used to convert the object
    to a dictionary. Effectively this means you can also use this method
    with `schema.Document` objects.

    :param documents: a sequence of dictionaries or `Document` objects, or
                      objects providing a ``items()`` method that can be
                      used to convert them to a dictionary
    :return: an iterable over the resulting documents
    :rtype: ``list``

    :since: version 0.2
    """

Как видите, эта функция не вызывает исключения, которые были вызваны сервером couchdb, а скорее возвращает их в кортеже с идентификатором документа, который мы хотели обновить.

Один из рецензентов отправился на #python по irc, чтобы спросить об этом. В #python они рекомендовали использовать дозорные значения, а не исключения. Как вы видите, просто подход не практичен, так как есть много возможных исключений, которые могут быть получены. Мои вопросы: каковы преимущества использования исключений над значениями часового, кроме того, что использование исключений более уродливо?

Ответы [ 4 ]

4 голосов
/ 22 января 2010

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

2 голосов
/ 22 января 2010

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

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

Python делает это внутренне в одном случае. Когда вы сравниваете два значения, например foo < bar, фактический вызов равен foo.__lt__(bar). Если этот метод вызывает исключение, поток программы будет прерван, как и ожидалось. Но если он возвращает NotImplemented, Python попытается вместо этого bar.__ge__(foo). Поэтому в данном случае возврат исключения, а не его поднятие используется для указания того, что оно не работает, но ожидаемым образом.

Это действительно разница между ожидаемой и неожиданной ошибкой, ИМО.

1 голос
/ 22 января 2010

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

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

Кстати, update () немного отличается:

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

В этой ситуации создание исключения НЕ будет полезным в API. С другой стороны, если соединение с базой данных прерывается во время выполнения запроса, исключение - это путь (так как это постоянная ошибка, которая повлияет на все последующие операции).

Кстати, если вашей бизнес-логике требуется, чтобы все операции выполнялись успешно, и вы не знаете, что делать в случае сбоя обновления (т. Е. Ваш дизайн говорит, что это никогда не произойдет), не стесняйтесь вызывать исключение в своем собственном коде .

1 голос
/ 22 января 2010

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

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

Я бы предложил вернуть docid, new_rev_doc кортеж в случае успеха и распространить / повысить исключение как есть Ваш подход дублирует success и тип 3-го возвращаемого значения тоже.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...