Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the cons of returning an Exception instance instead of raising it in Python?

I have been doing some work with python-couchdb and desktopcouch. In one of the patches I submitted I wrapped the db.update function from couchdb. For anyone that is not familiar with python-couchdb the function is the following:

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
    """

As you can see, this function does not raise the exceptions that have been raised by the couchdb server but it rather returns them in a tuple with the id of the document that we wanted to update.

One of the reviewers went to #python on irc to ask about the matter. In #python they recommended to use sentinel values rather than exceptions. As you can imaging just an approach is not practical since there are lots of possible exceptions that can be received. My questions is, what are the cons of using Exceptions over sentinel values besides that using exceptions is uglier?

like image 699
mandel Avatar asked Feb 28 '23 17:02

mandel


2 Answers

I think it is ok to return the exceptions in this case, because some parts of the update function may succeed and some may fail. When you raise the exception, the API user has no control over what succeeded already.

like image 85
olt Avatar answered Apr 28 '23 02:04

olt


Raising an Exception is a notification that something that was expected to work did not work. It breaks the program flow, and should only be done if whatever is going on now is flawed in a way that the program doesn't know how to handle.

But sometimes you want to raise a little error flag without breaking program flow. You can do this by returning special values, and these values can very well be exceptions.

Python does this internally in one case. When you compare two values like foo < bar, the actual call is foo.__lt__(bar). If this method raises an exception, program flow will be broken, as expected. But if it returns NotImplemented, Python will then try bar.__ge__(foo) instead. So in this case returning the exception rather than raising it is used to flag that it didn't work, but in an expected way.

It's really the difference between an expected error and an unexpected one, IMO.

like image 36
Lennart Regebro Avatar answered Apr 28 '23 02:04

Lennart Regebro