Writings of a techie wizard
 
Single Entry
Tue, 25 Sep 2012

Some time ago I posted about Go vs. Python with regard to delimiters. I now have another reason to prefer Python to Go: Go's error handling (hat tip: Hacker News).

To briefly see the issue, consider the following snippet of idiomatic Python:

with open(filename, 'r') as f:
    # do something with f

What happens if the open call fails? An exception is thrown. If we want to deal with it, we wrap the call in a try/except block:

try:
    with open(filename, 'r') as f:
        # do something with f
except IOError:
    # handle failure to open the file

Now consider the corresponding snippet of Go, taken from the blog post linked to above:

f, err := os.Open(filename)
if err != nil {
    // handle failure to open the file
}
// do something with f

Two things jump out at me by comparing the above snippets (leaving aside all the stuff about delimiters, etc. that I ranted about last time). First, if the file open fails, Python guarantees that the "do something with f" code will not execute; Go depends on the programmer putting something in the "handle failure to open file" code that does that. Of course, fixing that particular wart is easy:

f, err := os.Open(filename)
if err != nil {
    // handle failure to open the file
} else {
    // do something with f
}

Which of course begs the question, why didn't the blog post write it that way? Perhaps because the poster expected the "do something with f" code to test for a valid file object? In other words, they really intended to write this:

f, err := os.Open(filename)
if err != nil {
    // handle failure to open the file
}
if f != nil {
    // do something with f
}

(I'm assuming that testing for a non-nil f is sufficient; if it isn't, changing the if statement appropriately is straightforward.) In Python, no such testing of f is required:; Python guarantees that inside the with statement block (the "do something with f" code), f is a valid open file object. It can make that guarantee, of course, because it can guarantee that the block will not execute if the file open fails. In other words, Go forces the programmer to do things by hand that Python takes care of automatically, and since those things are, at least IMHO, "boilerplate" things that programmers shouldn't have to worry about, Python's method is preferable.

This by itself may not be a huge issue; but now consider the second thing that jumped out at me. In Python, I only need to wrap the with block in a try/except block if I want to handle the failure condition in that particular section of code. Otherwise, I just let the exception propagate until something catches it. This is, of course, the whole point of having exceptions as your error handling mechanism: it uncouples handling of errors from handling of normal conditions. Some people, apparently including the Go designers, consider this to be Very Bad Juju, and as you can see, in Go you have no choice about where you handle errors; you have to test for them and handle them locally, whether you want to or not.

Why might you not want to? Suppose I'm writing a library to open and parse a particular type of file. This library might be used by a variety of applications; some might be end-user apps for editing the file, while others might be server-side apps that just want a parsed object they can use to read attributes from. The way that a failure to open the file should be handled is very different for these two types of apps: the end-user app needs to display a message to the user (at least if it wants to be usable), while the server-side app probably should just log the error and go on, or perhaps send an urgent page to a sysadmin.

If I'm writing this library in Python, handling all this is simple, because error handling is uncoupled from normal functionality. Each app's code simply catches the IOError exception in the appropriate place and deals with it. In Go, what do I do? Either my library gets overgrown with error-handling code for all manner of possible use cases, even though I know far less about those use cases than the app writers do, or else I have to put together an elaborate system of callbacks, plugins, or what-have-you to deal with what is fundamentally a simple problem.

So once again, while it's great that people are trying new things with programming languages, I'm still sticking with Python.

Posted at 21:01   |   Category: rants   |   Tags: computers   |   Permalink
Wizard Projects
Site Links
Open Source Projects
simpleblog3
dev release
plib3.stdlib
dev release
plib3.classes
dev release
plib3.dbtools
dev release
plib3.io
dev release
plib3.gui
dev release
setuputils3
dev release
simpleblog
dev release
plib.stdlib
dev release
plib.classes
dev release
plib.dbtools
dev release
plib.io
dev release
plib.gui
dev release
setuputils
dev release
Old Open Source Projects
Python Recipes
Fun Stuff
Shameless Plugs
Copyright © 2011-2015
by Peter A. Donis
All Rights Reserved