Python - Is this an anti-pattern?

A place to discuss the implementation and style of computer programs.

Moderators: phlip, Moderators General, Prelates

Posts: 42
Joined: Thu Oct 08, 2015 4:56 am UTC

Python - Is this an anti-pattern?

Postby jacques01 » Sun Jul 31, 2016 7:31 pm UTC

A lot of my coding deals with talking to resources outside my control. These means a lot of network I/O. A lot can go wrong, and while I cannot control that, I have to decide how to handle errors when they occur, as it's important to log this and see any trends, etc. It can get more complicated if I introduce my own timeouts but let's forget about that for now.

A majority of my code follows this pattern:

Code: Select all

def foo(...):
      result = outsideResource(...)
      if result:'Result is OK')
         logger.warning('Got result but it's empty somehow')
         return None
   except Exception as e:
      #note it's bit more detailed here, just to give you the idea
      logger.error('Got some exception {} when doing action X'.format(str(e))
      return None

def bar(..):
   result = foo(..)
   if result:
      return True
   return False

This pattern is pervasive in a lot of my code. It's very repetitive. Is there a better way to gracefully accomplish this?

Posts: 278
Joined: Wed Jul 27, 2011 3:13 pm UTC

Re: Python - Is this an anti-pattern?

Postby Tub » Sun Jul 31, 2016 9:30 pm UTC

Your problems seem to be caused by your attempt to mix different error handling paradigms.

If you used exceptions only, bar() would not return a bool, but either succeed or throw. Same for outsideResource(). With that approach, bar() would just call outsideResource(), maybe do some logging and be done with it.

Or you could avoid exceptions, instead return bools or objects/None, in which case you get one simple function calling outsideResource(), then branching on the result and either logging success and returning true, or logging a failure and returning false.

Either implementation is concise and not an anti-pattern. Your long-windedness stems from the fact that you're switching between the paradigms - or even using both in a single function (like outsideResource).

My advice is to stick to one paradigm inside your core application; preferably the same paradigm that your standard library uses. (I personally like exceptions, but YMMV.) That keeps the amount of wrapper code minimal. Sometimes you have to wrap external libraries, but that can be handled.

If you must wrap methods this way, it probably won't get much shorter than your example. You could make a helper function that takes something callable, executes it, catches exceptions, logs everything, then either returns true or false, so your code reduces to
def bar()
return my_exception_wrapper(outsideResource)
However, as soon as you want to get situation specific logging text in there, or different logging priorities, or any other customization, that brevity is gone again.

Return to “Coding”

Who is online

Users browsing this forum: No registered users and 3 guests