0

I have code like this:

try:
    request=parse_request
except:
    print "cannot parse your malformed request"
    exit()
else:
    try:
        fh=a_factory_function()
    except:
        print "cannot create object"
    else:
        if request['operation']=='search':
            pass
        elif request['operation']=='more_like_this':
            pass
        elif request['operation']=='list_files':
            pass
        elif request['operation']=='update':
            pass
        else:
            print 'unsupported operation'

In present form it has two levels of indentation

  1. parse a request
  2. the factory function to generate an object to process the request

I can easily imagine this getting to 4 levels and becoming too complex for our puny reasoning. Is there a Pythonic way to flatten the indentation and make it "linear"?

Jesvin Jose
  • 22,498
  • 32
  • 109
  • 202

4 Answers4

2

Errors should not pass silently. If you ask me, printing a message instead of raising an exception in this situation counts as “silently”.

Calling exit() is worse – any time your function is called, no matter how deep in an imported library, a malformed request will kill the program.

The more Pythonic alternative to printing a message then ignoring the erorr, or calling exit(), is to let the caller of this code catch the exception and deal with it. You don't need any exception handling in this function.

If you need to distinguish between parse errors and object creation errors, raise a custom ParseError or ObjectCreationError and let the caller deal with that. As the other answers suggest, if a block ends with raise (or exit(), or return), there's no need for an indented else block after it.

Petr Viktorin
  • 65,510
  • 9
  • 81
  • 81
1

Unless I'm misinterpreting your code, you're using the else clause of the try statement for normal processing. In effect, you're simulating return code error handling with exceptions. Why not do this?

try:
    request=parse_request
    fh=a_factory_function()
except MalformedRequestError:
    print "cannot parse your malformed request"
    exit()
except CreateObjectError:
    print "cannot create object"
    exit()

if request['operation']=='search':
    pass
elif request['operation']=='more_like_this':
    pass
elif request['operation']=='list_files':
    pass
elif request['operation']=='update':
    pass
else:
    print 'unsupported operation'

There is a good answer by Blair Conrad here on StackOverflow that explains why you might want to use an else clause.

Community
  • 1
  • 1
dkobozev
  • 2,265
  • 2
  • 21
  • 21
0

In this case, you call exit() after catching the exception on top level, so you can do it this way:

try:
    request=parse_request
except:
    print "cannot parse your malformed request"
    exit()
try:
    # and so on
Griwes
  • 8,805
  • 2
  • 43
  • 70
0

Leave the function/script after each failure (as you do for the first failure) -- then you do not need to indent the following code, as it is not possible for it to run after a failure.

Depending on where this code is, you want to raise your own custom error, or return instead of exit.

try:
    request=parse_request
except:
    print "cannot parse your malformed request"
    exit()
try:
    fh=a_factory_function()
except:
    print "cannot create object"
    exit()
if request['operation']=='search':
    pass
elif request['operation']=='more_like_this':
    pass
elif request['operation']=='list_files':
    pass
elif request['operation']=='update':
    pass
else:
    print 'unsupported operation'
Ethan Furman
  • 63,992
  • 20
  • 159
  • 237