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…)

Wireless network “appears compromised”

Posted in Apple by garth on the January 19th, 2008

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.”

The wireless network appears to have been compromised...

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

Posted in kids by garth on the October 24th, 2007

Zephyr, this morning:

Zephyr big boy. Daddy big boy. Mummy big girl. Willow big chicken pox.

QuickPost Wordpress Plugin - Version .4 is now available

Posted in Wordpress by garth on the October 3rd, 2007

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

Posted in Misc by garth on the September 4th, 2007

Yep. Quadruple-barrelled.

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

Posted in Django, Python by garth on the September 1st, 2007

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?

Posted in Meta, Wordpress by garth on the August 27th, 2007

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

Posted in Misc, Wordpress by garth on the August 2nd, 2007

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. 

Next Page »

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