Default arguments in Python: two easy blunders
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
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?
Just before Twitter went completely dark, I saw this:

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…)
Wireless network “appears compromised”
I’m seeing a lot of this disturbing little error message: “The wireless network appears to have been compromised and will be disabled for about a minute.”

A poke around the Internet doesn’t show much other than other people complaining about the same problem. Some find the only way to solve the problem is to disable WPA. I’m not so sure that’s a smart idea. I hope there’s a fix for this in 10.5.2.
[If you're getting this on what you think is a Django-only feed, it's because the community feed administrators haven't yet updated their subscription to point to my Django posts only. Sorry about that.]
Zephyr’s sense of humour, age 2.5
Zephyr, this morning:
Zephyr big boy. Daddy big boy. Mummy big girl. Willow big chicken pox.
QuickPost Wordpress Plugin - Version .4 is now available
QuickPost Wordpress Plugin - Version .4 is now available
So far, so good, except for the database error (wp_categories doesn't exist) under WordPress 2.3…
Admiral Sir Reginald Aylmer Ranfurly Plunkett-Ernle-Erle-Drax
I always wondered what'd happen if one double-barrelled person married another double-barrelled person. Reg Drax here seems to be Exhibit A.
Our kids are double-barrelled. To save them from Reg' fate, we carefuly chose their middle names so they could ditch the two surnames entirely if necessary.
Thanks, Merlin!
Django vs feedparser on dates
I'm having trouble storing feedparser results in a Django model.
It's all about timestamps. Feedparser returns timestamps in a standard time nine-tuple, asserting UTC. Django wants datetime objects. So, I'm trying to translate:
django_timestamp = datetime.datetime.fromtimestamp(time.mktime(feedparser_timestamp))
feedparser_timestamp = django_timestamp.utctimetuple()
This works fine for the majority of timestamps, but sometimes translating to datetime and back mutates the timestamp. In turn, that makes get-if-modified-since somewhat unreliable. Here are some examples, from my log file:
WARNING: (2004, 11, 19, 5, 13, 31, 4, 324, 0) => datetime.datetime(2004, 11, 19, 6, 13, 31) => (2004, 11, 19, 6, 13, 31, 4, 324, 0)
WARNING: (2005, 11, 2, 2, 17, 55, 2, 306, 0) => datetime.datetime(2005, 11, 2, 3, 17, 55) => (2005, 11, 2, 3, 17, 55, 2, 306, 0)
WARNING: (2006, 12, 13, 0, 21, 25, 2, 347, 0) => datetime.datetime(2006, 12, 13, 1, 21, 25) => (2006, 12, 13, 1, 21, 25, 2, 347, 0)
WARNING: (2004, 11, 14, 23, 55, 31, 6, 319, 0) => datetime.datetime(2004, 11, 15, 0, 55, 31) => (2004, 11, 15, 0, 55, 31, 0, 320, 0)
I'm off by an hour. I smell a problem with daylight savings. I just wish I knew what to do about it.
I've waved a dead chicken at this one all the ways I know how. Every change I make breaks the conversion entirely. So, I'm throwing this out to the community in the hope that someone can help me.
Push the tempo?
I'm much more likely to post to Twitter, Tumblr and Facebook than here. The environments are pleasantly slack: I don't feel like I have to write masses of highly insightful prose.
Today, I noticed another key factor: their tools are optimised for speed of posting. You can tweet or tumble as fast as you can send an instant message. For whatever reason, I feel a lot more drag than that when trying to post in Wordpress.
I've installed TIQPWP to see if it helps. Already, I've noticed one thing I like: when I hit Enter, I get a new paragraph rather than a line break.
Result so far: first post in a billion years. Well, a month. Whatever.
[Django Community Blog subscribers: if you see this, the administrator hasn't yet updated my feed. Sorry about that.]
0wn3d
My web host just rang me to ask me to upgrade WordPress. Some benefactor of humanity had used a hole in WordPress to turn his web server into a spam-bot, and he was going to get black-holed any minute. Rather than turn me off entirely, he rang me. How's that for customer service? I sincerely doubt I'd get that from, say, GoDaddy.