Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do we use try,except in every single function?

Should we always enclose every function we write with a try...except block? I ask this because sometimes in one function we raise Exception, and the caller that calls this function doesn't have exception

def caller():
   stdout, stderr = callee(....)


def callee():
   ....
    if stderr:
       raise StandardError(....)

then our application crash. In this obvious case, I am tempted to enclose callee and caller with try..except.

But I've read so many Python code and they don't do these try..block all the time.


def cmd(cmdl):
    try:
        pid = Popen(cmdl, stdout=PIPE, stderr=PIPE)
    except Exception, e:
        raise e
    stdout, stderr = pid.communicate()
    if pid.returncode != 0:
        raise StandardError(stderr)
    return (stdout, stderr)

def addandremove(*args,**kwargs):
    target = kwargs.get('local', os.getcwd())
    f = kwargs.get('file', None)
    vcs = kwargs.get('vcs', 'hg')

    if vcs is "hg":
        try:
            stdout, stderr = cmd(['hg', 'addremove', '--similarity 95'])
        except StandardError, e:
            // do some recovery
        except Exception, e:
            // do something meaningful
    return True

The real thing that bothers me is this:

If there is a 3rd function that calls addandremove() in one of the statements, do we also surround the call with a try..except block? What if this 3rd function has 3 lines, and each function calls itself has a try-except? I am sorry for building this up. But this is the sort of problem I don't get.

like image 718
CppLearner Avatar asked Jul 13 '12 21:07

CppLearner


People also ask

When should you use try-except?

The reason to use try/except is when you have a code block to execute that will sometimes run correctly and sometimes not, depending on conditions you can't foresee at the time you're writing the code.

Should you try catch every function?

It's not recommended nor economical to put try-catch in every function and block code. Instead, create a separate class for exception handling and log exceptions here, then show or handle these exceptions.

Can try work without Except?

First try clause is executed i.e. the code between try and except clause. If there is no exception, then only try clause will run, except clause will not get executed. If any exception occurs, the try clause will be skipped and except clause will run.

How do you use try and except in a function?

The Python try… except statement runs the code under the “try” statement. If this code does not execute successfully, the program will stop at the line that caused the error and the “except” code will run. The try block allows you to test a block of code for errors.


2 Answers

Exceptions are, as the name implies, for exceptional circumstances - things that shouldn't really happen

..and because they probably shouldn't happen, for the most part, you can ignore them. This is a good thing.

There are times where you do except an specific exception, for example if I do:

urllib2.urlopen("http://example.com")

In this case, it's reasonable to expect the "cannot contact server" error, so you might do:

try:
    urllib2.urlopen("http://example.com")
except urllib2.URLError:
    # code to handle the error, maybe retry the server,
    # report the error in a helpful way to the user etc

However it would be futile to try and catch every possible error - there's an inenumerable amount of things that could potentially go wrong.. As a strange example, what if a module modifies urllib2 and removes the urlopen attribute - there's no sane reason to expect that NameError, and no sane way you could handle such an error, therefore you just let the exception propagate up

Having your code exit with a traceback is a good thing - it allows you to easily see where the problem originate, and what caused it (based on the exception and it's message), and fix the cause of the problem, or handle the exception in the correct location...

In short, handle exceptions only if you can do something useful with them. If not, trying to handle all the countless possible errors will only make your code buggier and harder to fix


In the example you provide, the try/except blocks do nothing - they just reraise the exception, so it's identical to the much tidier:

def cmd(cmdl):
    pid = Popen(cmdl, stdout=PIPE, stderr=PIPE)
    stdout, stderr = pid.communicate()
    if pid.returncode != 0:
        raise StandardError(stderr)
    return (stdout, stderr)

# Note: Better to use actual args instead of * and **,
# gives better error handling and docs from help()
def addandremove(fname, local = None, vcs = 'hg'):
    if target is None:
       target = os.getcwd() 

    if vcs is "hg":
        stdout, stderr = cmd(['hg', 'addremove', '--similarity 95'])
    return True

About the only exception-handling related thing I might expect is to handle if the 'hg' command isn't found, the resulting exception isn't particularly descriptive. So for a library, I'd do something like:

class CommandNotFound(Exception): pass

def cmd(cmdl):
    try:
        pid = Popen(cmdl, stdout=PIPE, stderr=PIPE)
    except OSError, e:
        if e.errno == 2:
            raise CommandNotFound("The command %r could not be found" % cmdl)
        else:
            # Unexpected error-number in OSError,
            # so a bare "raise" statement will reraise the error
            raise

    stdout, stderr = pid.communicate()
    if pid.returncode != 0:
        raise StandardError(stderr)
    return (stdout, stderr)

This just wraps the potentially confusing "OSError" exception in the clearer "CommandNotFound".

Rereading the question, I suspect you might be misunderstanding something about how Python exceptions work (the "and the caller that calls this function doesn't have exception" bit, so to be hopefully clarify:

The caller function does not need any knowledge of the exceptions that might be raised from the children function. You can just call the cmd() function and hope it works fine.

Say your code is in a mystuff module, and someone else wants to use it, they might do:

import mystuff

mystuff.addandremove("myfile.txt")

Or, maybe they want to give a nice error message and exit if the user doesn't have hg installed:

import mystuff

try:
    mystuff.addandremove("myfile.txt")
except mystuff.CommandNotFound:
    print "You don't appear to have the 'hg' command installed"
    print "You can install it with by... etc..."
    myprogram.quit("blahblahblah")
like image 94
dbr Avatar answered Sep 30 '22 18:09

dbr


You should use a try catch block so that you can specifically locate the source of the exception. You can put these blocks around anything you want, but unless they produce some sort of useful information, there is no need to add them.

like image 32
Rob Wagner Avatar answered Sep 30 '22 19:09

Rob Wagner