Category Archives: Uncategorized

Not a Python Programmer

If someone asks you if you’re a Python (or Java, or Javascript or language X) programmer, how do you respond? This year, my answer will be “No. I’m not a Python programmer, I’m a programmer”

Last year, I wrote production code in:

  • Python
  • Ruby
  • Javascript
  • Java
  • Objective-C
  • C
  • Powerpoint (only joking!)

I narrowly avoided writing code in Erlang, and considered writing some getting-to-know you Golang, but alas writing all the other code ate the available time.

As one of my Comp Sci professors said many years ago, learning any language takes a day or two provided you’re familiar with the language style (functional, imperative, OO etc etc). What takes the time is learning the libraries and the idiom. However, I’ve noticed that this takes way less time than it did back in the day, thanks to Google, Github and Stack Overflow.

Now, if you have a “there must be a better way” feeling when working with a new language, it’s the work of moments to find it and learn the relevant idiom. As an aside: one of the great disappointments of last year was realising how shockingly bad the idioms for writing network code on Android are.

So I’m a programmer first and foremost, who uses whichever tool makes sense while trying to cultivate a constant sense of laziness and curiosity. Laziness so I look for the easy way, and the curiosity to find it.

Let’s see which languages make the list in 2014…


OS X Mavericks: Fixing broken Android dev environments

OS X Mavericks has also broken my Android development environment by removing ant.

The fix is simple: download and install ant from

While I was at it, I also updated to the latest Android SDK from Not necessary, but why not while fixing things.

Making Django runserver more awesome

I’ve recently found Dave Cramer’s awesome devserver and it already feels like an essential part of my Django toolkit. It’s a drop-in replacement for the default Django development server

./ runserver

But with a whole host of seriously useful additions if you care about what’s going on behind the scenes:

  • Log of SQL queries issued
  • Cache hits/misses
  • Werkzeug  debugger
  • Memory usage

And loads more. A picture’s worth a thousand words, so here goes:

[sql] SELECT ...
 FROM "polls_numericpoll"
 INNER JOIN "polls_event" ON ("polls_numericpoll"."event_id" = "polls_event"."id")
 WHERE ("polls_event"."slug" = doi
 AND "polls_numericpoll"."enabled" = TRUE
 AND "polls_event"."enabled" = TRUE)
 ORDER BY "polls_event"."start_time" DESC, "polls_numericpoll"."order" DESC LIMIT 1
 [sql] SELECT ...
 FROM "polls_numericpoll"
 INNER JOIN "polls_event" ON ("polls_numericpoll"."event_id" = "polls_event"."id")
 WHERE "polls_numericpoll"."id" = 2011343691
 [sql] 2 queries with 0 duplicates
 [cache] (3ms) 32 calls made with a 83% hit percentage (5 misses)
[05/Mar/2012 17:08:27] "GET /api/1.0/show/doi/state HTTP/1.1" 200 1179 (time: 0.15s; sql: 0ms (2q))

[cache] (1ms) 7 calls made with a 83% hit percentage (1 misses)
[05/Mar/2012 17:09:21] "GET /api/1.0/show/doi/state HTTP/1.1" 200 1179 (time: 0.01s; sql: 0ms (0q))

The [sql] lines show how the DB was hit on the first pass, and the second request shows that the caching is working perfectly – everything is then served from cache. Having tracked down several scaling issues where something was secretly doing database calls, this is just great for quickly identifying what’s going on. The best bit? Installation is trivially simple:

  1. Install via pip
    pip install git+git://
    INSTALLED_APPS = ( 'devserver', ....)

After that, there’s a bunch of useful extensions to make things even better – head over to the project page for all the details.

Raspberry Pi – but not till May

When the Raspberry Pi was announced, I went and registered with both Farnell & RS for one. Alas I wasn’t one of the first 10,000, so it was waiting list time.

On Thursday I got the mail saying Farnell would now take my order. Yay!

Order placed, I eagerly awaited the delivery notification. Would it be a week? Maybe two? Try nearer 8 – it’s due to arrive on the 30th April 2012. I hope it’s worth the wait.

Raspberry Pi ordered!

Have just placed my order for a Raspberry Pi. Haven’t been this excited about getting a new computer/gadget since Lego Mindstorms.

My current favourite hack for it is to port a BBC B emulator to it, then wire up in an old Beeb box and use it to play HD Elite on the big TV. So 1980’s.

A post a day

This post is about regular posting – and changing behaviour. I believe under international law all bloggers are allowed one post about how difficult posting regularly is – this is my contribution to the oeuvre!

A while back I resolved to post more regularly, but as the evidence here shows that resolution was a failure. Then recently I finished reading Switch – How to Change Things When Change is Hard. Changing into a regular poster certainly seemed hard, and I knew I’d failed before. Could Switch help me?

A few key ideas seemed like they could help:

  1. Shrink the Challenge. Instead of trying to post regularly forever, make it for a week
  2. Black and White goal. Instead of posting regularly, change to post every work day. No wiggle room there!
  3. Celebrate progress. Note I’m posting this on Wednesday, having already made 2 posts this week. Yay, I’m 40% of the way there!
  4. Instant habits. Set an “action trigger” for when I’m going to write a post each day. For me, it’s after each day’s scrum meeting.

I don’t yet know if I will succeed in changing into a regular blogger, but so far the techniques seem to be working. More on Switch in a future post…

Memcached can count – pylibmc can’t

In my recent talk to Big Data London I said that memcached can’t count. Turns out that’s not really true, and the problem lies somewhere else.

Here’s the original evidence memcached has counting issues, using Python & pylibmc:

In [2]: cache.set('wibble', 0)

In [3]: cache.get('wibble')

Out[3]: 0

In [4]: cache.decr('wibble', 1)
Out[4]: 0L

In [5]: cache.incr('wibble', 1)
Out[5]: 1L

In [6]: cache.incr('wibble', -1)
Out[6]: 4294967296L

Incrementing by -1 has resulted in memcached incrementing by 2^32-1 – a classic signed/unsigned conversion problem.

But hang on – according to the memcached spec, incr takes unsigned 64bit integers – and it’s an error to send a signed number.

Sure enough, using the ASCII protocol (with memcached 1.4.9):

get wibble
VALUE wibble 0 1
incr wibble -1
CLIENT_ERROR invalid numeric delta argument

It seems memcached can count after all, or at least refuse to do operations it might get wrong. It’s another question why memcached won’t deal with signed numbers…

So where’s the weird behaviour above coming from? It’s a couple of bugs in pylibmc – bug 74 and bug 73.

The good news? Both bugs are now fixed in the latest github version, so very soon memcached and pylibmc will be able to count. Three cheers – hooray, hooray!