Archive for the 'Code' Category

Inline callbacks with Twisted and Python 2.5

A while ago I wrote about Defgen, which lets you use generator syntax to write Python code in a “blocking” format. I thought it was pretty cool, but it required some strange backflips to work right.

Yesterday, Glyph showed me something that was added to Twisted trunk a little while ago: inlineCallbacks. It’s the same concept, but because it uses the new yield syntax in Python 2.5, it’s even prettier.

Here’s the current source from doc/core/examples/ampclient.py:

from twisted.internet import reactor, defer
from twisted.internet.protocol import ClientCreator
from twisted.protocols import amp
from ampserver import Sum, Divide

def doMath():
    d1 = ClientCreator(reactor, amp.AMP).connectTCP(
        '127.0.0.1', 1234).addCallback(
            lambda p: p.callRemote(Sum, a=13, b=81)).addCallback(
                lambda result: result['total'])
    def trapZero(result):
        result.trap(ZeroDivisionError)
        print “Divided by zero: returning INF”
        return 1e1000
    d2 = ClientCreator(reactor, amp.AMP).connectTCP(
        ‘127.0.0.1′, 1234).addCallback(
            lambda p: p.callRemote(
                Divide,
                numerator=1234,
                denominator=0)
            ).addErrback(trapZero)
    def done(result):
        print ‘Done with math:’, result
    defer.DeferredList([d1, d2]).addCallback(done)

Here’s what it looks like using inlineCallbacks:

@defer.inlineCallbacks
def doMath():
    client = ClientCreator(reactor, amp.AMP)
    conn = yield client.connectTCP('127.0.0.1', 1234)
    sumResult = (yield conn.callRemote(Sum, a=13, b=81))['total']
    try:
        divideResult = yield conn.callRemote(
            Divide, numerator=1234, denominator=0)
    except ZeroDivisionError:
        print “Divided by zero: returning INF”
        divideResult = 1e1000
    result = [sumResult, divideResult]
    print ‘Done with math:’, result
    defer.returnValue(result)

It’s infinitely more legible. I’ve always hated the process of writing callback-driven procedures, just because the code no longer flows top-to-bottom. Even a simple client-side operation gets mangled (like above). But with inlineCallbacks, your code looks totally synchronous; it’s just executed asynchronously.

Too bad it’s only usable on Python 2.5. That means only Twisted-based applications can use it; the Twisted library itself won’t shed backwards-compatibility for a long time.

Sorry I missed it

Sounds like PyCon 2007 was a good time. I’m interested to hear what happened with the Twisted Birds-of-a-Feather sessions, or whether there was any illuminating material in the Pybots talk. For the record, Moshe, I didn’t avoid Texas because I hate everyone; it’s because I hate you in particular.

Next year, though, I’ll be there. I can’t miss an opportunity to visit Chicago. Kudos to ChiPy for getting approval for their Chicago 2008 bid. I’m looking forward to it already.

Defgen: Just one more reason that Twisted freakin’ rocks

This isn’t brand-spanking new (it’s been in trunk for quite a while already), but Bob Ippolito made an update to it recently, so it caught my eye. I think this is such a cool, and incredibly useful, part of Twisted, that it’s worth mentioning just for anybody who hasn’t seen it yet.


from twisted.internet import reactor
from twisted.internet import defer

waitFor = defer.waitForDeferred

def getSomeDeferred():
    d = defer.Deferred()
    reactor.callLater(
        2, d.callback, 'This is a string that yells "foo!"')
    return d

def anotherDeferred(needle, haystack):
    d = defer.Deferred()
    reactor.callLater(
        2, d.callback, haystack.find(needle))
    return d

@defer.deferredGenerator
def find(needle):
    d = waitFor(getSomeDeferred())
    yield d
    haystack = d.getResult()
    print 'I got my first deferred result'
    d = waitFor(anotherDeferred(needle, haystack))
    yield d
    print 'I found', repr(needle), 'at character', d.getResult()
    return

find('foo!')
reactor.run()


So now you can write deferred procedures that look synchronous. None of this “writing many small statements, nested, backwards” nonsense. That’s awesome.

Updated: I noticed that the code I wrote didn’t really demonstrate the power of deferredGenerator, so I’ve updated the code. I still think this is really cool.

How do we keep an ecosystem of frameworks useful to newcomers?

The first day of Pycon 2005 is wrapping up, and we’re heading to dinner soon. Attending the sprints was a good way to get ramped up before the talks; I think if I hadn’t been breathing Python 24/7 for a few days first, I might not have been able to follow anything.

I won’t comment on everything at once, but of the three web talks I attended, one piqued my interest (WSGI), one was really cool (Donovan’s LivePage/LiveTest/Canvas demonstration), and one struck a chord. Michelle Levesque put together an ongoing project called PyWebOff, comparing major Python web application frameworks from a user’s point of view.

She started off with a very good point: that Googling Python web application framework brings up a laundry list of different frameworks, each with different capabilities, features, strengths and weaknesses, levels of documentation, and sets of assumptions about the average user’s capabilities. To contrast, Googling for Ruby web application framework comes up with one application, Ruby on Rails, which will do nearly everything you want in an elegantly simple way (though not in Python).

So what can we do about web application frameworks? The archetypical beginner, who loves Python for its ease of use but has only ever used PHP (or ASP, or ColdFusion, or CGI) for creating web sites, will probably give up fairly quickly if they get started in the wrong place. Michelle’s assertion that a plethora of choices is confusing is valid, but I question her conclusions. Her talk closed with the argument that we need to slim down the number of Python web frameworks and settle on three “major” frameworks: one for “large” applications, one for “medium” applications, and one for “small” applications. (She also made a plea for nobody to release another web application framework after her talk, which may have some impact, but probably not as much as we’d like.)

It is tempting to cut across the vast number of existing web frameworks and toolkits and broadly classify them. A meme I hear from many people is that they can be divided into “big”, “medium”, and “small”; another is that frameworks are “process-driven”, “thread-based”, and “event-driven”. These are properties, yes, but they are not the only properties which web application developers need to consider.

I think we need a User’s Guide to Python Web Application Frameworks (or something with a slightly better name), to help newbies to Python web programming make sense of the myriad choices available to them. It wouldn’t need to get into the itchy details, but it would need to explain why there are so many frameworks available. Most times that someone reinvented the “web framework” wheel, it’s because they made a conscious design decision to do something differently.

When someone says, I don’t care about the details, I just want to write a web page, that’s a valid position only to a certain degree. Unless you plan on writing plain CGI, you can’t expect to start writing web applications without understanding some of the basic concepts behind these frameworks; you don’t need to know details, but you do need to know why people keep deciding to reinvent the wheel. Choice is good; uninformed choice is dangerous.

I won’t delve into why I think Twisted Web and Nevow are great tools for building web applications, and why I think these tools are much better than tools like CherryPy (even for small applications). That’s personal preference, and I think the Python web application community needs to learn to put personal preferences aside and help newcomers to make their own choices. Otherwise, their choice may very well be Rails.

Introducing Loco.moxn

I’ve started a moblog, inspired by pages like Joi Ito‘s Moblog2 and mass-appeal sites like TextAmerica. I know, I’m a total geek, and I realize that nobody’s interested in seeing blurry pictures taken from my mundane life. I’m just doing it just because I can, and because it was fun setting up the system. I’ve also created a sidebar here that shows the latest picture from my moblog, because, frankly, don’t expect anyone to actually track Loco.moxn itself.

An email gets sent from my mobile phone to a secret email address, which then gets passed through a Perl script, chopped up into pieces, and fed into Movabletype. It took some fine-tuning to get the templates to work properly, but it was easy enough.

Ah, and you thought I’d be writing something insightful, about politics, media, technology, or why China and India are eating our lunches. Sorry, no such luck. Maybe in a couple days. Until then, look to the right for some blurry pictures of my cats.

Gloating because I was right

I know, it’s really poor form to jump around and gleefully snicker, “I told you so,” but sometimes I can’t resist.

I pointed out a few months back that the new file dialogs in GNOME 2.6 were poorly designed. The exclusion of a text box from the “Open” dialog, among other things, reflects a truly deep ignorance of how users actually use GNOME — as opposed to how GNOME‘s developers believe users should use GNOME. (I originally posted to FootNotes, where people really flamed me for my heresy.)

Well, it looks like I’m not the only one who’s less than enthusiastic about having the GNOME developers play dictator with the user interfaces we’ve grown accustomed to. A review of Fedora Core 2 on Linux.com diverges for an entire paragraph (with requisite screenshot) about how stupid the “Open” dialog box is. Nick Petreley writes in a Computerworld opinion piece, “I can only assume that the GNOME developers decided to make Nautilus a worse Windows than Windows. I toast their rousing success.”

It’s time to come back to the real world: features are great, but not when they impose an unnecessary learning curve on the average user. Even I find this “new” interface too much hassle for the benefits, and I am very used to keyboard shortcuts for everything.

I never saw justification for another total revamp of the dialog boxes; all they needed was to add the “Locations” list to the side of the 2.4 dialogs, and we’d be happy. Instead, we are pissed.

So I, too, would like to raise a bottle of beer to the failure of the GNOME team to produce a usable interface. Chin chin, boys.

Update: I suppose I should check Planet Twisted before delivering a rant, just to make sure Glyph hasn’t already ranted on the same topic, but with far more eloquence and tact than I could’ve hoped for. Oh well. Like I said, flame away.

And the crowd goes wild

Everyone is going crazy over the release of Movable Type 3.0. Some people have flamed Six Apart, accusing them of deception, smuggling drugs, and killing baby seals.

I’m not happy with the way things turned out, I think this was a bad business decision, and I certainly believe Six Apart could use some help with public relations. However, I think this company has every right to attempt to change their business model, and when it upsets their user community, we have every right to take our business elsewhere.

It’s obvious that Six Apart has refocused its core approach to the blogging business. Timothy Appnel repeated a rumor that they got less than 50¢ per download; if that’s true, I can understand why they felt the need to change their licensing structure.

Movable Type was never free software, though, and a lot of bloggers seem to have missed that part. We were always forbidden from redistributing the software. Nobody was ever allowed to fork Movable Type. It was always “proprietary”, but with a very loose set of rules. Those rules are now a lot stricter, but Six Apart’s business model has not changed. It’s just been recalibrated, and I don’t think they’ve done a great job.

The new Six Apart is two products: TypePad and Movable Type. If you’re a regular blogger and you want something quick, cheap, and flexible, get TypePad. If you’re a “power user” who plans on using Movable Type as a development platform or extended CMS (as many people have done), then there is an expectation that you’ll be able to pay for the privilege of using it.

For the record, I’m not upgrading to MT 3.0 unless the licensing system changes. Right now I manage three blogs (Cogito and Natasha’s two blogs), and I plan on starting more fairly soon (including a moblog, once I can afford picture messaging). This disqualifies me from the free version (maximum of one author and three weblogs), and the next step up (five authors, five weblogs) is $70 — and soon to be $100. I simply can’t afford that, and I think 2.x works well enough for the time being.

While I wish Mena and Ben the best of luck in their business, if I were in their shoes, I would’ve done things a lot differently. Part of the reason MT is such a good development platform is because it has a wide user base and a very large community of plugin developers. Many of the people in this community cannot (or are simply unwilling to) pay high fees for software which is heavily commoditized. There are dozens of blogging systems out there, and some (like WordPress) are actively courting MT users. Converting from one system to another is easy enough; Mark Pilgrim has already done it, and his site was one of the most complex MT installations I’ve seen.

I suppose the folks at Six Apart figured they could ignore this “middle band” of their user community, keeping only the very hard-core developers on MT and the very lightweight users on MT Free or TypePad. My own belief is that the people who can no longer justifiably use MT 3.0 are actually the ones who did most of the active development of MT plugins and extensions, and that cutting these folks off is tantamount to suicide by stagnation. (Many other bloggers agree.) Time will tell; I’d like to think Six Apart did research before landing on this specific licensing scheme, and that they have a clear view of where their business is headed. But that’s not always a given.

As for me, I’m part of the “middle band” that Six Apart has thumbed its nose at. I run my own web server, I need my own installation (not some blogs.com subdomain) and I need flexibility as well. Yet I can’t justify spending hundreds of dollars for MT 3.0 when there are so many equally powerful alternatives, available for free — not free as in beer, but free as in speech.

Moving forward, I’d like to use a system that I know I’ll be able to upgrade without additional restrictions. WordPress seems to have a fairly good user community, but it’s PHP, and that grates on my sensibilities. (Granted, MT is Perl+CGI, and that’s only slightly better.) Perhaps this will give me some incentive to finish writing my own blogging system using Nevow. We’ll see. For the time being I’m sticking to MovableType, but I’m not upgrading past 2.x — and I suspect a lot of other people will do the same.

Update: Six Apart has clarified and revised some of the licensing terms in Movable Type 3.0; as I’d expected, it was not just refocusing their business model, but also a really bad PR job. Nonetheless, it doesn’t seem like there’s a lot of reason for me to upgrade any time soon. My current setup works well already; I’ll wait for the “real” release of MT3 before deciding whether to migrate to a truly free platform or stay with theirs (or roll my own).

Shifting gears

I’ve redesigned my site using ASP.NET, and starting today I’ll be using Microsoft’s Internet Information Services instead of Twisted Web. After carefully considering the costs and benefits, I decided that ASP and IIS 5.0 offer superior performance and functionality to my handrolled Python nonsense, and that the increased productivity is well worth the extra licensing fees I’ll be paying for IIS, Windows Server 2003, and whatever upgrades I’ll need over the next few years.

Yay, Microsoft! Boo, Linux!