Ask Forgiveness Not Permission

This is a programming notion rather than the recipe for a long and happy marriage!

As I’ve been reading, I’m been coming across many references to the pythonic principle of Ask Forgiveness Not Permission.

It’s not difficult. You probably know it. You just didn’t know it had that name.

An example of asking permission would be:

if (i_can_do_it):
    do_it
else:
    do_something_else

vs the ask forgiveness approach of:

try:
    do_it
except (i_cant_do_it):
    do_something_else

There are a couple of main reasons behind the practice.

Firstly, in any concurrent system there is the potential for there to be a race condition between the evaluation of i_can_do_it and the action of do_it (see more from db code example below).

Secondly, the comprehensive list of things you need to check for permission may be lengthy and/or not be possible to either know or cover in their entirety so you end up having to cover the exceptions anyway.

So, going back to my roots, you often see this pattern in PLSQL and SQL with a SELECT check followed by a subsequent action if something exists:

begin
    ...
    begin
      select ... from ....
      do something;
    exception 
    when no_data_found then
         do something else
    end;
    ...
end;
/

Apart from anything else, another session may have inserted or deleted a row in between the time in which you did the select and you then attempting the subsequent do_something.

Better to attempt the do_something and then react to the no_data_found exception or react to the attributes of SQL%ROWCOUNT/FOUND/NOTFOUND.

Advertisements

Beginnings of Flask, Conda, Pip

This week I am mostly getting to grips with Flask, initially using this tutorial.

This is a gentle introduction to using a virtual Python environment using Conda at work and pip at home and getting to grips with my initial IDE of choice, PyCharm.

I installed a bunch of packages, realised I had installed them globally – not just to my new virtual environment for my Flask tutorial – uninstalled globally, reinstalled locally and now back on track.

I haven’t done any of the wirings from Flask into the DB but, initially at least, so many of the concepts are very familiar from recent learnings with Angular – model, view, controllers, factories, routing, etc.

Simple stuff but all good reusable learnings which are relatively new to this particular dinosaur.

Pythonic Zen: Failures and Exceptions

From my initial learnings on  Python, I have been struck by the message that there is a very strong sense of things being Pythonic, i.e.there being a Python-way of doing things.

Here I’m going to talk about coding for failures.

There are two approaches dealing with program execution and an operation which might fail:

  • LBYL
  • EAFP

Look Before You Leap – Check that all possible failure conditions for a failure-prone operation are met in advance of attempting the operation.

It’s Easier to Ask Forgiveness than Permission – Hope for the best and deal with the consequences.

In a simple example, this might mean that rather than doing a whole bunch of type checking on an object passed before doing an action (LBYL), it is a preferred approach to try to do it and then catch the exceptions if it fails (EAFP).

Below is another example. Consider some noddy LBYP code which processes a file:

import os
p = '/mypath/myfile.txt'
if os.path.exists(p):
    process_file(p)
else:
    ...some exception code...

Problems include:

  • if check clutters the “happy path” through the code
  • ‘exists’ is only one of quite a few conditions we might check
  • something might happen to our file between the check and the process such that the file would no longer pass the checks so we have to code for the exception anyway.

Compare and contrast the EAFP approach:

p = '/mypath/myfile.txt'
try:
    process_file(p)
except OSError as e:
    ...some exception code...

EAFP in conjunction with Exceptions, rather than bespoke error/return codes, is considered to be the Pythonic way.

Further reading: