« | » Main « | »

Better error messages

Wednesday 28 July 2010

A simple piece of advice: If you are throwing an exception (or logging an error) about a value being incorrect in some way, include the value itself. It will make it so much easier for the poor sap who has to figure out why the exception is happening.

I found myself in this situation, this code throwing an exception:

if not isinstance(key, str):
    raise Client.MemcachedStringEncodingError, ("Keys must be str()'s, not"
            "unicode.  Convert your unicode strings using "

There are a few things wrong with this message, the first being that the multi-line string concatenation is missing a space, so the message actually has the word "notunicode" in it. Why are we so sure the wrong value is Unicode in the first place? And of course, it should include the actual value:

if not isinstance(key, str):
    raise Client.MemcachedStringEncodingError, (
        "Keys must be str()'s: %r" % key

If you want to be paranoid, you can limit the amount of repr text that will appear in the message:

if not isinstance(key, str):
    raise Client.MemcachedStringEncodingError, (
        "Keys must be str()'s: %.60r" % key

If you are really paranoid, you're worried that getting the repr of your unknown object could itself throw an exception:

def safe_repr(o):
        return repr(o)
        return "??norepr?"


if not isinstance(key, str):
    raise Client.MemcachedStringEncodingError, (
        "Keys must be str()'s: %.60s" % safe_repr(key)

or even:

def safe_repr(o):
        return repr(o)
    except Exception, e:
        return "??norepr (%s)?" % e

Good error handling is always a pain, but it's worth it when things start hitting the fan and you have to figure out what's going on.

Whitespace in Ruby and searching for code

Tuesday 27 July 2010

Armin's post about Whitespace sensitivity in Ruby piqued my interest. It points out that in Ruby, foo[42] is different than foo [42] and that foo/bar is the same as foo / bar but different than foo /bar.

So I wanted to learn more about Ruby, and looked at a bunch of tutorials, finally ending up at Mitch Fincher's Ruby Tutorial with Code Samples, which had the right breezy pace with no, "a variable is like a box for your numbers" stuff in it.

But I had originally gotten to Mitch's page from a Google search for ruby puts gets. If you try it, you'll see that when you get to Mitch's page, a small box appears near the top, saying,

Welcome. You seem to have come here from a search engine. Your search words (ruby puts gets) are highlighted on this page for your reading pleasure.

I thought "nice," then I thought, "that looks familiar," then I realized it was almost exactly the box that appears at the top of my pages when you visit from a search engine (try it: batchelder white house adventure). In fact, it used the same colors. I looked at his page, and it used near-verbatim copies of my three Javascript files, though a few years ago I consolidated them into one.

I was amused, and wondered where else the code is being used. But the search engines are smart enough not to index comments in Javascript files, or names of Javascript files referenced in HTML pages, unless there's some tricky syntax I don't know about.

PS: about whitespace sensitivity: I've decided that phrase means a programming language needs tokens consisting of only whitespace in order to be parsed properly. Python and Ruby are whitespace-sensitive, and C is not, for example.

Making Peace with Autism in Korean

Sunday 18 July 2010

My wife's book Making Peace with Autism is now available in Korean: 자폐아 가정의 좌충우돌 성장 이야기.

Making Peace with Autism in Korean

The publishing business is a strange place. The first we knew the book was being translated into Korean was when a box of the books was delivered to our doorstep. Apparently there was also an entry in the latest sales statement from the publisher, but those things are completely indecipherable, so we didn't notice.

The Korean culture also seems to value cute more than we Americans do: the book is full of cartoony decorations. I guess that chipper salaryman on the cover is me!

Installing Python packages from Windows installers into virtualenv

Saturday 17 July 2010

Note (Feb 3, 2016): the latest and best version of this is Alex Waters' onetruepython. Use that.

I'm a recent convert to virtualenv, it's a great way to maintain a number of different Python installations so that you can install packages for one project without it polluting the environment for all your projects.

I also work on Windows, which can be a pain. In particular, many interesting Python packages involve compiling extensions, which is not always easy, and especially not easy on Windows. So I'm glad when package authors provide pre-built binaries for Windows. These are typically delivered as .exe Windows installers.

Here's the problem: these installers know to look in the registry to find the Python installation. There are many things developers dislike about Windows, and the registry is often at the top of the list. One of the bad things about it is that it encourages a mindset of their being one of everything. Starting with the concept of "one registry", it seeps into the whole culture of Windows, invading even to Python, which cannot abide more than one installation of a major release.

So when running a Windows package installer, it will find the Python 2.6 installation in the registry, and that's the only option you've got for where the code is going to go. Your nice isolated virtualenvs are completely out of the picture.

I asked on Stack Overflow if there's a way to install Windows package installers into virtualenvs, and didn't get the answers I wanted.

So I decided the best approach was to change the registry, install my package, then change the registry back. I adapted a classic script to register Python installations, to create what I've called the_python.py:

# script to register Python 2.0 or later for use with win32all
# and other extensions that require Python registry settings
# Adapted by Ned Batchelder and Alex Waters from a script
# written by Joakim Low for Secret Labs AB / PythonWare
# source:
# http://www.pythonware.com/products/works/articles/regpy20.htm

import sys

from _winreg import *
import ctypes
import ctypes.wintypes
import os.path

# tweak as necessary
version = sys.version[:3]
installpath = sys.prefix

regpath = "SOFTWARE\\Python\\Pythoncore\\%s\\" % (version)
installkey = "InstallPath"
pythonkey = "PythonPath"
pythonpath = "%s;%s\\Lib\\;%s\\DLLs\\" % (
    installpath, installpath, installpath

def RegisterPy():
        reg = OpenKey(HKEY_LOCAL_MACHINE, regpath)
    except EnvironmentError:
            reg = CreateKey(HKEY_LOCAL_MACHINE, regpath)
        except Exception, e:
            print "*** Unable to register: %s" % e

    SetValue(reg, installkey, REG_SZ, installpath)
    SetValue(reg, pythonkey, REG_SZ, pythonpath)
    print "--- Python %s at %s is now registered!" % (version, installpath)
    raw_input('Press any key...')

class SHELLEXECUTEINFO(ctypes.Structure):
    _fields_ = (

def need_admin():
    ShellExecuteEx = ctypes.windll.shell32.ShellExecuteEx
    ShellExecuteEx.restype = ctypes.wintypes.BOOL
    sei.cbSize = ctypes.sizeof(sei)
    sei.lpVerb = "runas"
    sei.lpFile = sys.executable
    sei.lpParameters = os.path.abspath(__file__)
    sei.nShow = 1

if __name__ == "__main__":
    except WindowsError as e:
        if e.errno == 13:

Use your desired Python to run this script, and it will be entered into the registry as the Python. When you run your Windows package installer, it will go into your virtualenv. Don't forget to run it again at the end to put things back the way they were.

Updated Nov 12, 2013: Alex Waters ([Tritium] on #python) revised the program to detect the need for elevated privileges and automatically re-run itself with privileges. This makes it much more convenient. Thanks, Alex!

Updated Feb 3, 2016: Alex Waters continues dominance in this area: his latest version is at onetruepython.

Zach Anner

Friday 16 July 2010

Zach Anner is a funny guy, who happens to have cerebral palsy, as Zach puts it, "the sexiest of the palsies". He submitted a video to Oprah's Search for the next TV star:

He ended up with 2.5 million votes:

I really like Zach's humor because it doesn't avoid his disability, and it isn't just about his disability. It's about funny Zach and the funny world, and Zach's cerebral palsy is part of it, but just a part. He strikes just the right balance, and he's got a great attitude. Watch him train for the 2011 Austin marathon:

He has more stuff with Lark the Beard. I hope he goes far.

Recent tweets

Monday 5 July 2010

¶  RT @catherinedevlin: I am so moving to France. Castle under construction w/ 100% historical technology. http://tinyurl.com/3acrbve (Jul 02)

¶  Awesome and sweet.. RT @sgalineau: http://www.youtube.com/watch?v=-CVYOCMpJRY #classic #starwars (via @bcongdon) (Jun 28)

¶  Not often you get bitingly mean graphic design humor: RT @jackschofield: Missing cat poster story http://www.27bslash6.com/missy.html [Cat lovers beware] (Jun 25)

¶  Tons of recreational math stuff! Sadly, no RSS: http://www.mathpuzzle.com/ (Jun 20)

¶  The Omnificent English Dictionary In Limerick Form: http://www.oedilf.com. Really. (Jun 20)

¶  iPad + autism = win! http://www.blogher.com/ipad-nearmiracle-my-son-autism (Jun 18)

¶  About time we took a hard look at couch architecture: http://blog.buildllc.com/2010/04/couch-cushion-architecture-a-critical-analysis/ lol. (Jun 09)

¶  Pretty, in a geometry/typography kind of way: http://www.flickr.com/photos/quasimondo/4644498892/in/photostream/ See the paintings in the stream too. (Jun 05)

¶  RT @sgalineau: Once in a while Smashing Mag surprises: Arabic, East Asian and Indic calligraphy & writing systems http://www.smashingmagazine.com/2010/05/18/the-beauty-of-typography-writing-systems-and-calligraphy-of-the-world/ #i18n (May 29)

« | » Main « | »