Deadly Bloody Serious


Default arguments in Python: two easy blunders

Posted in Django, Misc, Python by garth on the May 9th, 2008

I’m glad I stumbled across Patrick Altman’s tweet about a “default bug in Django“. I’d never have guessed you can pass a callable to a field’s default= argument, otherwise. That’s quite a powerful idiom, and I think I’ll use it a lot.

To balance the karma, I’d like to post a quick reminder to everyone else that expressions in default arguments are calculated when the function is defined, not when it’s called. In Patrick’s code, for example, all objects created in the same running session got the same timestamp. Try this in the Python interactive prompt:

>>>import time
>>> def report(when=time.time()):
…     print when
…
>>> report()
1210294387.19
>>> time.sleep(5)
>>> report()
1210294387.19

Until the interpreter quits, you’ll always get the same timestamp. The correct way to go about this is to default to None or some other sentinel, then replace it inside the function:

>>> def report(when=None):
…     if when is None:when = time.time()
…     print when
…
>>> report()
1210294762.29
>>> time.sleep(5)
>>> report()
1210294772.23

Now that you know about that blunder, you should be able to figure out what’s going on with this second classic blunder when using default arguments in Python:

>>> def spam(eggs=[]):
…     eggs.append(”spam”)
…     return eggs
…
>>> spam()
['spam']
>>> spam()
['spam', 'spam']
>>> spam()
['spam', 'spam', 'spam']
>>> spam()
['spam', 'spam', 'spam', 'spam']

Twitter Emergency Backup

Posted in Python by garth on the May 5th, 2008

Dave Winer has been thinking about ways to preserve the Twitter community even when Twitter is down. His latest effort is a web service to save Twitter feeds and expose their content via another feed.

I tried it out, but couldn’t parse the response:

Python 2.5.1 (r251:54863, Jan 17 2008, 19:35:17)
[GCC 4.0.1 (Apple Inc. build 5465)] on darwin
Type “help”, “copyright”, “credits” or “license” for more information.
>>> import xmlrpclib, urllib2
>>> twittergram = xmlrpclib.Server(”http://rpc.twittergram.com/RPC2/”)
>>> content = urllib2.urlopen(”http://twitter.com/statuses/user_timeline/704593.rss”).read()
>>> twittergram.saveFeed(’garthk’, ‘*****’, content)
Traceback (most recent call last):
  File ““, line 1, in 
  File “/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/xmlrpclib.py”, line 1147, in __call__
    return self.__send(self.__name, args)
  File “/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/xmlrpclib.py”, line 1437, in __request
    verbose=self.__verbose
  File “/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/xmlrpclib.py”, line 1201, in request
    return self._parse_response(h.getfile(), sock)
  File “/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/xmlrpclib.py”, line 1335, in _parse_response
    p.feed(response)
  File “/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/xmlrpclib.py”, line 547, in feed
    self._parser.Parse(data, 0)
xml.parsers.expat.ExpatError: mismatched tag: line 10, column 7

I’ll investigate later.

I’d love to wade into this kind of problem domain, perhaps using Google App Engine for hosting so I didn’t have to worry about usage spikes. Feed backup is a brilliant start. We also need to helping our followers find the feeds, and I’m sure more thought will yield more areas for funimprovement.

Twitter’s Famous Last Words?

Posted in Misc by garth on the May 2nd, 2008

Just before Twitter went completely dark, I saw this:

last words

I’m sure it’ll be back up soon, but ’twas nice to have a laugh before hitting the sack.

(Speaking of irony: I have 666 unread items in my feed reader’s Productivity folder…)


Bad Behavior has blocked 2642 access attempts in the last 7 days.