Add to Technorati Favorites

Leaving Barcelona

13:40 October 7th, 2011 by terry. Posted under me. | 2 Comments »

I’m leaving Barcelona on October 19th and have a bunch of stuff I need to get rid of before then. If you’re interested anything below, please let me know ASAP. You’ll need to come pick things up in the Born, right next to Santa Maria del Mar. I’ve not put prices on anything. So either make an offer or tell me why I should just give you what you want for free. You can reach me via email to terry at-sign jon dot es.

  • Cheap ironing board
  • Braun iron
  • Vacuum cleaner
  • Dell DN1815 multi-function networked laser printer (black & white). Fax, copy, scan, print. 5 years old, works great.
  • 20" Miyata deluxe (48 spoke) unicycle
  • 26" Semcycle unicycle
  • 6 Renegade juggling clubs
  • Bag of about 15 silicone juggling balls
  • 2 minitorre computers (from about 2002) without hard drives
  • 3 Ikea CD shelves (each holds about 200 CDs)
  • 7 60cm wide x 2.5m tall white Ikea (Billy) bookshelves
  • 1 40cm wide x 2.5m tall white Ikea (Billy) bookshelf
  • 1 30cm wide x 2.5m tall white Ikea (Billy) bookshelf
  • 19" CRT monitor
  • 2 100Mbit ethernet hubs (5 port, 8 port)
  • 5 cable modems (DLink, Cisco, 3Com)
  • 2 Siemens Gigaset AS29H DECT phones, like new, white
  • White wooden Ikea TV/DVD table
  • Massive (3m by 1.2m) wall-mounted whiteboard
  • White Ikea filing cabinet (2 wide roll-out shelves)
  • Green wooden 6-drawer small rolling shelves
  • DVD player with sub-woofer & 5 external speakers
  • Sony CD player with sub-woofer & 2 external speakers
  • Panasonic NVGS230 hand-held video recorder, perfect condition
  • K2 rollerblades 6000 series, good condition, size 41/42
  • 5-wheel speed skates, size 41/42
  • Philips toaster
  • Large wooden Ikea cutting board
  • Kettle
  • Electric juice extractor
  • Hand-held electric blender
  • Barcelona apartment floor tiles. I have about 20 that I’ve accumulated over the years.

fishus

03:58 August 16th, 2011 by terry. Posted under other. | Comments Off on fishus

Date: Tue, 26 Sep 95 15:55 MDT
From: mosterin@hydra.unm.edu (Ana Mosterin)
To: dsmith@cs.unm.edu

well, you should love wild cooking too
you have to find the right attitude:

you have to be sensitive enough
to feel the fear and shudder a bit at what you’re doing
and to love your piece of fishus enough
to touch it and smell it
with patience and lust
and then aaaaaaaarrrh! sacrifice it
and chop it skillfully
and be matter-of-fact enough
to to act like you’ve done it before
and professionally dry your hands
with your apron
and and have your hands on your hip
as you listen and smell to
the sound of the frying
breath in through your nose
as you watch the pan with love and think
“no, no more garlic,
just a half-cup of wine”
and relax!
it’s the ferocious poetry
of the wild cooking job
and then eating it will be twice as lovely
you’ll see

hey, derek,
cooking is not mary poppins!


La Storia di San Michele

04:16 August 8th, 2011 by terry. Posted under books, me. | 3 Comments »

Image: Villa San Michele

[Written in 2003, as the first of a two-part story of a remarkable connection. Here’s part two.]

Axel Munthe

In 1928, Axel Munthe, a Swedish physician living on the isle of Capri, published The Story of San Michele. Munthe’s villa on the slopes of Mount Barbarossa stands on a site chosen almost two thousand years earlier by the emperor Tiberius, who from tiny Capri held sway over the entire Roman empire. Extraordinarily beautiful, the island passed at various times through the hands of the Greeks, the Romans (Caesar Augustus was captivated), the Dutchy of Naples, the Saracens, the Longobards, the Normans, the Angevins, the Aragonese, the Spanish, and the Bourbons.

On completing his medical studies, Munthe was the youngest physician in Europe. The Story of San Michele describes his time in Paris and Rome, his years as the physician to the Swedish Royal family and later his years as private physician to the queen of Sweden, who had also taken a liking to Capri. Written in English, The Story of San Michele, which remains in print, was an instant success, becoming the best-selling non-fiction book in the U.S. in 1930. Munthe’s novel approach to medicine and the book’s mixture of adventure, treasure, and royalty continue to inspire. The Story of San Michele was the mysterious target of one Henry Arthur Harrington, a petty thief who crisscrossed the UK, stealing 1,321 copies from second-hand bookstores before his eventual arrest in 1982. Even in 2003, Munthe’s contributions are the subject of learned attention: the Second International Symposium on Axel Munthe’s life and work will be held in Sweden tomorrow (September 13).

With the rapid success of The Story of San Michele, the book was a natural target for would-be translators. Editions in several languages were soon completed. Given its origin, it was odd that such a popular book was not more quickly translated into Italian.

Patricia Volterra

Living in Florence, Patricia Volterra was fascinated by the book and was eager for her husband Gualti to read it too. A minor obstacle: Gualti did not speak English. Undeterred, Volterra decided to translate the book into Italian. She wrote to John Murray, the publisher, requesting permission. To her surprise, she received a reply directly from Munthe. From Volterra’s diary, Munthe told her that:

the book had already been translated into several languages and was selling like wildfire. To date he had refused offers for it to be translated into Italian as, he wrote, this language, when written, was apt to become too flowery and overloaded and that he had written the book in an extremely simple style which he wished to retain. However, he continued, he suggested I should translate the last chapter, which he considered the most difficult, and send it to him to the Torre Matterita at Anacapri. He would then let me know whether he thought he could permit me to translate the rest.

Volterra sent off her translation of the final chapter and spent several weeks waiting for an answer. Finally her manuscript was returned “with an extremely complimentary letter from Munthe, telling me to proceed to do the rest.” Later she wrote that at that time nothing seemed impossible to her but that now she wouldn’t have even considered the translation.

While working on the translation, she had lunch with Munthe in Rome when Gualti, an Italian concert pianist, was playing at the Augusteum. Munthe was staying at Villa Svezia, the Queen of Sweden’s residence on the Via Aldovrandi. When Munthe saw her he exclaimed ‘My goodness, how old are you?’ She: ‘Twenty three.’ He: ‘And you are translating San Michele!’ Munthe was over 70 at the time.

Volterra sent the work to an Italian publisher, Mondadori, who refused her. “Their great loss,” she wrote. Another, Treves, accepted. Munthe “had decreed that the entire royalties should go to the Society for the Protection of Animals in Naples.” Volterra was to sell her translation for whatever she could get for it. This amounted to the equivalent of 50 pounds sterling for 8 months work.

Later that spring, Volterra traveled to Capri. In a horse-drawn cab they drove to Anacapri where they visited San Michele. From there on foot through the olives to the Torre di Materita to have lunch with Munthe. A variety of his dogs scampered round his heels as he showed them the old tower which was then his home. They had a vegetarian lunch served by Rosina, so affectionately mentioned by Munthe in his book.

The Volterra translation ran quickly into 35 editions and was still selling well when she left Italy in 1938. Mussolini was so impressed by La Storia di San Michele that he passed a law prohibiting the shooting of migratory birds on Capri.

Volterra saw Munthe one final time, in Jermyn Street, London. Munthe died in 1949, leaving the villa of San Michele to Sweden. Owned today by the Swedish Munthe Foundation, it is home to an ornithological research center and is open to the public.

[Continued in part two, "Bob Arno".]


Bob Arno

04:16 August 8th, 2011 by terry. Posted under barcelona, books, me. | 3 Comments »

Image: ABC Tasmania

[Written in 2003, this is the 2nd part of the story of a remarkable connection. You’ll need to read part one for the set up.]

For the last seven years, I’ve kept a web page full of people’s email about street scams they’ve been involved in (as victims) in Barcelona.

In the beginning I just wrote down brief descriptions of things that I saw or was involved in soon after moving to Spain. I’d seen hardly any street crime in my (then) 33 years and I found it fascinating to watch for. It certainly wasn’t hard to find. Often it came right to my door or to the street under my balcony. Before long I began to receive email from others who had visited or lived in Barcelona, each with their own story to tell. I put the stories onto the web page and they soon outnumbered my own. I continue to receive a few emails a month from people who’ve read the web page (generally after being robbed, though sometimes before leaving on a trip). I don’t often reply to these emails, apart from a line or two to say thanks when I put their messages on the web page, often months after they mail me.

For whatever reason, I’ve never been very interested to meet these people, though I’ve had plenty of chances to. In general I don’t seem to have much interest in meeting new people – it’s quite rare that I do. I should probably be more sociable (or something) because once in a while the consequences are immediately extraordinary.

Among my email, I get occasional contacts from people in the tourism industry. Lonely Planet, Fodor’s, people writing books or running travel services or web sites. Mainly they want to know if they can link to the web page, or to use some of the content in their own guides. I always agree without condition. After all, the main (but not the only) point is to help people be more aware, and besides, the majority of the content was written by other people who clearly share the same advisory aim. With this attention from various professionals who are trying to pass on the information, I began to wonder how many such people there were. Maybe there were other people with web sites devoted to street crime. So once in a while I’d do a web search on “street scams”, or something similar, just to see what came up. It’s usually interesting.

On July 30th 2001, I went looking around for similar web sites and ran across Bob Arno. I took a quick look around and fired off an email to say hello, and offered to buy him a beer the next time he was in Barcelona:

    Hi Bob

    I was just having a wander around the web when I ran into your
    pages about pickpockets. They look good, very useful.

    You might be interested to see a page of my own: http://jon.es/barna/scams.html

    All about things that have happened to people in Barcelona. It's
    not too well organized, but there's a lots of it. Most of it falls
    into well known classes of petty crime. Things are getting worse
    here, with the most recent tactics being strangulation from behind
    and squirting a flammable liquid onto people's backs and then, you
    guessed it, setting them on fire.

    Let me know next time you're in Barcelona and I'll buy you a
    beer. I'm also in Manhattan very often.

    Regards,
    Terry Jones.

Bob looked very interesting, and we seemed to have the same point of view on street crime. He’s a seasoned professional, a Vegas showman, and is constantly traveling the world studying many forms of crime and passing on his knowledge. Check out his website.

I sent mail to Derek, passing on Bob Arno’s URL. I said a little of how funny and random it seemed to me, of how over all the years of doing different things and meeting any number of famous and high-powered academics and intellectuals etc., and not really having much interest in any of them, that I’m sending email to this Bob Arno guy suggesting we meet up.

The next day I read more about Bob’s exploits and interests and I guessed that we would probably get on really well. I sent off a longer email with some more of my observations about Barcelona:

    Hi again.

    I sent off that first email without having looked at more than a
    page or two of your web site.

    It's very interesting to read more. I spend far too much time
    thinking about and watching for petty thieves in Barcelona. I've
    thought about many of the issues touched on in the interview with
    you by your own TSJ. The whole thing is very intriguing and lately
    I've begun to wonder increasingly what I can do about it, and if I
    want to do anything about it. I have tended to act to try to stop
    pickpockets, but I've also seen things many times from a distance
    or a height, read many things, seen freshly robbed people weeping,
    talked to many people who have been robbed, thought of this as an
    art (I'm interviewed in a Barcelona newspaper under the headline
    "Some crimes are a work of art" - I'm not sure if they understood
    what I meant), etc. I've never tried filming these people. But I
    know how they look at you when they know they have been spotted,
    how their faces look when the wallet hits the floor, how they prey
    on Western or "rich" psychology, and so many other things.  My
    focus has been Barcelona, after coming to live here 5 years ago
    and (at that time) having an apartment 1 floor up about 100 meters
    from Plaza Real. If I had had a net I could have caught people
    several times a day.

    I recently got a video camera and was thinking of interviewing the
    woman on my web site who was strangled here earlier this month. By
    the way, the papers reported up to 9 cases of such stranglings in a
    single day. I wasn't quite sure what to do with the tape. It hadn't
    occurred to me to film the thieves, but it would be so easy.  In
    Barcelona it's trivial to spot these people, and also feels very
    safe since many of them have been arrested literally hundreds of
    times.  There is basically no deterrent. There are undoubtedly more
    sophisticated pickpockets here too, but there is little in the way
    of evolutionary pressure to make them improve their methods. The
    tourists are too many and too unaware, the police are too few, and
    the laws are too slack. Why would you even bother to improve or
    think?

    I also know the boredom that comes with professional acts. I used to
    do a lot of juggling and unicycling, practicing 6 hours a day for a
    long time. But I could never stand to have a canned show that I did
    time after time - it was just too routine to have a routine. So I
    refused and eventually drifted into other things.

    How can I get a copy of your book? It doesn't seem to say on the web
    site. Also, the menu of links at the top left of your pages looks
    extremely garbled under my browser (Opera).

    Terry

As it turned out, my timing was perfect. I got a mail back the next day from Bob’s wife Bambi (yes, really). She said they’d be in Barcelona in just 5 days time and that they’d love to meet up.

And meet up we did!

They came to our apartment and we all hit it off immediately. As I’d thought, we did have a lot in common, both in terms of what we had done and in outlook. They told me they also get lots of email through their web site and hardly ever reply. Ana and I took them out for food. We sat outside at the nearby Textile Museum. Later, Ana went home to look after Sofia, and I stayed with Bob and Bambi. In the end I was with them about five hours and I had a really good time. We arranged to meet the next day to go hunting for thieves on the Ramblas. In one sense, “hunting” isn’t at all the right word: the thieves are typically very obvious to anyone who’s actually paying attention. But there’s a lot of subtlety in tracking and filming them, so it really is something like a hunt. I’ve since spent many hours, on several occasions, in action with Bob and Bambi in Barcelona. But that’s another story.

After getting home that first night, I went back to Bob’s web site and read more of his pages. He’s had a pretty colorful life. Actually, it’s extraordinarily colorful by almost any measure. “Who is this Bob Arno?” I wondered. Fortunately, Bob has a “Who is Bob Arno?” page, which I finally got around to reading.

Halfway down… unbelievable… I want to cry.

    Born in Sweden, Bob Arno is a great-grandson of Dr. Axel Munthe,
    who is most famous for his novel The Story of San Michele.

Patricia Volterra was my great aunt.


txdpce: a Twisted class for deferred parallel command execution

13:43 July 12th, 2011 by terry. Posted under deferreds, python, twisted. | Comments Off on txdpce: a Twisted class for deferred parallel command execution

I just uploaded a simple Twisted Python class, txdpce, to Launchpad. It’s designed for situations where you have multiple ways of obtaining a function result and you want to try them all in parallel and return the result from the fastest function. A typical case is that you can either compute a result via a network call or try to get it out of a cache (perhaps also via a network call, to memcached). You might also be able to compute it locally, etc.

Things can be more complicated than provided for here, of course. E.g., you might like to cache the result of a local call (if it finishes first or if the cache lookup fails). The txdpce class is supposed to be a simple demonstration. I wrote it for a bit of fun this morning and also because it’s yet another nice example of how you can click together the building blocks of Twisted to form increasingly sophisticated classes.

Here’s the class. You’ll find a test suite at the Launchpad site. You can download the code using bzr via bzr branch lp:txdpce.

from twisted.internet import defer
from twisted.python import failure


class ParallelCommandException(Exception):
    pass


class DeferredParallelCommandExecutor(object):
    """
    Provides a mechanism for the execution of a command by multiple methods,
    returning the result from the one that finishes first.
    """

    def __init__(self):
        self._functions = []

    def registerFunction(self, func):
        """
        Add func to the list of functions that will be run when execute is
        called.

        @param func: A callable that should be run when execute is called.
        """
        self._functions.append(func)

    def execute(self, *args, **kwargs):
        """
        Run all the functions in self._functions on the given arguments and
        keyword arguments.

        @param args: Arguments to pass to the registered functions.

        @param kwargs: Keyword arguments to pass to the registered functions.

        @raise RuntimeError: if no execution functions have been registered.

        @return: A C{Deferred} that fires when the first of the functions
        finishes.
        """
        if not self._functions:
            raise RuntimeError('No execution functions have been registered.')

        deferreds = [defer.maybeDeferred(func, *args, **kwargs)
                     for func in self._functions]
        d = defer.DeferredList(deferreds, fireOnOneCallback=1, consumeErrors=1)
        d.addCallback(self._done, deferreds)
        return d

    def _done(self, deferredListResult, deferreds):
        """
        Process the result of the C{DeferredList} execution of all the
        functions in self._functions. If result is a tuple, it's the result
        of a successful function, in which case we cancel all the other
        deferreds (none of which has finished yet) and give back the
        result.  Otherwise, all the function calls must have failed (since
        we passed fireOnOneCallback=True to the C{DeferredList} and we
        return a L{ParallelCommandException} containing the failures.

        @param deferredListResult: The result of a C{DeferredList} returned
        by self.execute firing.

        @param deferreds: A list of deferreds for other functions that were
        trying to compute the result.

        @return: Either the result of the first function to successfully
        compute the result or a C{failure.Failure} containing a
        L{ParallelCommandException} with a list of the failures from all
        functions that tried to get the result.
        """
        if isinstance(deferredListResult, tuple):
            # A tuple result means the DeferredList fired with a successful
            # result.  Cancel all other deferreds and return the result.
            result, index = deferredListResult
            for i in range(len(self._functions)):
                if i != index:
                    deferreds[i].cancel()
            return result
        else:
            # All the deferreds failed. Return a list of all the failures.
            failures = [fail for (result, fail) in deferredListResult]
            return failure.Failure(ParallelCommandException(failures))


A resizable dispatch queue for Twisted

16:19 June 27th, 2011 by terry. Posted under deferreds, python, tech, twisted. | Comments Off on A resizable dispatch queue for Twisted

In December 2009 I posted to the Twisted mailing list about what I called a Resizable Dispatch Queue. I’ve just spent some time making a new version that’s much improved. You can pick up the new version via pip install txrdq, from PyPI, or from the txRDQ project page on Launchpad. Here’s the example use case, taken from my original posting:

You want to write a server with a web interface that allows people to enter their phone number so you can send them an SMS. You anticipate lots of people will use the service. But sending SMS messages is quite slow, and the company that you ship those jobs off to is concerned that you’ll overrun their service (or maybe they have an API limit, etc). So you need to queue up jobs locally and send them off at a certain rate. You’d like to be able to adjust that rate up or down. You also want to be able to shut your service down cleanly (i.e., not in the middle of a task), and when you restart it you want to be able to re-queue the jobs that were queued last time but which hadn’t gone out.

To make the example more concrete, suppose your function that sends the SMS is called sendSMS and that it takes a (number, message) tuple argument. Here are some of the kinds of things you can do:

from txrdq.rdq import ResizableDispatchQueue

# Create a queue that will allow 5 simultaneous underway jobs.
rdq = ResizableDispatchQueue(sendSMS, 5)

# Later... send off some SMS messages.
d1 = rdq.put((2127399921, 'Hello...'), priority=5)
d1.addCallback(...)

d2 = rdq.put((5052929919, 'Test...'), priority=5)
d2.addCallback(...)

# Cancel the second job
d2.cancel()

# Widen the outgoing pipeline to 10 simultaneous jobs.
rdq.width = 10

# We're dispatching jobs too fast, turn it down a little.
rdq.width = 7

# Get a copy of the list of pending jobs.
jobs = rdq.pending()

# Cancel one of the pending jobs from the jobs list.
job.cancel()

# Reprioritize one of the pending jobs from the jobs list.
rdq.reprioritize(job, -1)

# Arrange to increase the number of jobs in one hour.
reactor.callLater(3600, rdq.setWidth, 20)

# Pause processing.
rdq.pause()

# Resume processing, with a new width of 8.
rdq.resume(8)

# Shutdown. Wait for any underway jobs to complete, and save
# the list of jobs not yet processed.

def saveJobs(jobs):
    pickle.dump(jobs, ...)

d = rdq.stop()
d.addCallback(saveJobs)

I’ve come up with many uses for this class over the last 18 months, and have quite often recommended it to people on the #twisted IRC channel. Other examples include fetching a large number of URLs in a controlled way, making many calls to the Twitter API, etc.

Usage of the class is very simple. You create the dispatch queue, giving it a function that will be called to process all jobs. Then you just put job arguments as fast as you like. Each call to put gets you a Twisted Deferred instance. If your function runs successfully on the argument, the deferred will call back with an instance of txrdq.job.Job. The job contains information about when it was queued, when it was launched, when it stopped, and of course the result of the function. If your function hits an error or the job is canceled (by calling cancel on the deferred), the deferred will errback and the failure will again contain a job instance with the details.

It’s also useful to have an admin interface to the queue, so calls such as pending and underway are provided. These return lists of job instances. You can call cancel on a job instance too. You can reprioritize jobs. And you can pause processing or shut the queue down cleanly.

The code also contains an independently useful Twisted classes called DeferredPriorityQueue (which I plan to write about), and DeferredPool (which I described earlier).


Back of the envelope calculations with The Rule of 72

02:03 June 20th, 2011 by terry. Posted under other, tech. | 6 Comments »

Image: internetworldstats.com

The Rule of 72 deserves to be better known among technical people. It’s a widely-known financial rule of thumb used for understanding and calculating interest rates. But others, including computer scientist and start-up founders, are often concerned with growth rates. Knowing and applying the rule of 72 can help in developing numerical literacy (numeracy) around growth.

For example, consider Moore’s Law, which describes how "the number of transistors that can be placed inexpensively on an integrated circuit doubles approximately every two years." If something doubles every two years, at what rate does it increase per month, on average? If you know the rule of 72, you’ll instantly know that the monthly growth rate is about 3%. You get the answer by dividing 72 by 24 (the number of months).

Computer scientists are usually very familiar with powers of two. It’s often convenient to take advantage of the fact that 2^10 is about 1,000. That means that when something increases by a factor of 1,000, it has doubled about 10 times. By extension, and with a little more error, an increase of a million corresponds to 20 doublings, and a billion is 30 doublings (log base two of a billion is actually 29.897, so the error isn’t too wild). You can use this to ballpark the number of doublings in a process really easily, and go directly from that to a growth rate using the rule of 72.

For example, the bottom of this page tells us that there were about 16,000 internet domains on July 1st 1992, and 1.3M of them on July 1st 1997. Let’s think in thousands: that’s a jump from 16 to just over 1,000 in 5 years. To get from 1 to 16 is four doublings, so from 16 to 1,000 is six doublings (because 1,000 is ten doublings from 1). So the number of domains doubled 6 times in 5 years, or 6 times in 60 months, or once every 10 months (on average). If you want something to double in 10 months, the rule of 72 tells us we need a growth rate of 7.2% per month. To check: 16,000 * (1.072 ^ 60) = 1,037,067. That’s a damned good estimate (remember that we were shooting for 1M, not 1.3M) for five seconds of mental arithmetic! Note that the number of domains was growing much faster than Moore’s law (3% per month).

You can quickly get very good at doing these sorts of calculations. Here’s another easy example. This page shows the number of internet users growing from 16M in December 1995 to 2,072M in March of 2011. That’s just like the above example, but it’s 7 doublings in 15.25 years, or 183 months. That’s pretty close to a doubling every 24 months, which we know from above corresponds to 3% growth per month.

You can use facility with growth rates to have a good sense for interest rates in general. You can use it when building simple (exponential) models of product growth. E.g., suppose you’re launching a product and you reckon you’ll have 300K users in a year’s time. You want to map this out in a spreadsheet using a simple exponential model. What should the growth rate be? 300K is obviously not much more than 256 * 1,024, which is 18 doublings in 365 days, or a doubling roughly every 20 days. The rule of 72 gives 72/20 = ~3.5, so you need to grow 3.5% every day to hit your target. Is that reasonable? If it is, it means that when you hit 300K users, you’ll be signing up about 3.5% of that number, or 10,500 users per day. As you can see, familiarity with powers of two (i.e., estimating number of doublings) and with the rule of 72 can give you ballpark figures really easily. You can even use your new math powers to avoid looking stupid in front of VCs.

The math behind the rule of 72 is easy to extend to triplings (rule of 110), quadrupling (rule of 140), quintupling (rule of 160), etc.

Finally, you can use these rules of thumb to do super geeky party tricks. E.g., what’s the tenth root of two? Put another way, what interest rate do you need for something to double after ten periods? The rule of 72 tells you it’s 72/10 = 7.2%, so the tenth root of two will be about 1.072 (in fact 1.072 ^ 10 = 2.004). What’s the 20th root of 5? The rule of 160 tells you you need 160/20 = 8% growth each period, so 1.08 should be about right (the correct answer is ~1.0838).

As with all rules of thumb, it’s good to have a sense of when it’s most applicable. See the wikipedia page or this page for more detailed information. It’s also of course good to understand that it may not be suitable to model growth as an exponential at all.


How to asynchronously exchange a dictionary using Twisted deferreds

18:13 June 10th, 2011 by terry. Posted under deferreds, python, twisted. | Comments Off on How to asynchronously exchange a dictionary using Twisted deferreds

Here’s a fun class that I can’t think of a good use for :-) But I like its simplicity and it’s another illustration of what I like to call asynchronous data structures.

Suppose you have a producer who’s building a dictionary and a consumer who wants to look things up in it. The producer is working at their own pace, making new dictionary entries in whatever work order that suits them, and the consumer is requesting dictionary items in whatever order they need them. The two orders are obviously extremely unlikely to be the same if the dictionary is of non-trivial size. How do you write an asynchronous server (or data structure) that sits between the producer and consumer?

Yes, it’s far fetched, perhaps, but here’s a simple asynchronous dictionary class that lets you do it gracefully:

from collections import defaultdict
from twisted.internet import defer

class DeferredDict(dict):
    def __init__(self, *args, **kwargs):
        self._deferreds = defaultdict(set)
        dict.__init__(self, *args, **kwargs)

    def __getitem__(self, item):
        try:
            return defer.succeed(dict.__getitem__(self, item))
        except KeyError:
            d = defer.Deferred()
            self._deferreds[item].add(d)
            return d

    def __setitem__(self, item, value):
        if item in self._deferreds:
            for d in self._deferreds[item]:
                d.callback(value)
            del self._deferreds[item]
        dict.__setitem__(self, item, value)

When a consumer tries to get an element from the dictionary, they always get a deferred. The deferred will fire with the value from the dictionary when (if) it becomes available. Of course if the value is already known, they get it in a deferred that has already fired (via succeed). When the producer puts an element into the dictionary, any consumer deferreds that were waiting on that element’s value are given the value.

Note that a __delitem__ isn’t needed, we just inherit that from dict. If a non-existent item is deleted, you get the normal dictionary behavior (a KeyError). If the item does exist, that means the list of waiting deferreds on that item is empty (the fact the item exists means any waiting deferreds for the item have all been fired and that that item in the self._deferreds dictionary was deleted), so we can just let the dictionary class delete the item, as usual.


Graceful shutdown of a Twisted service with outstanding deferreds

17:42 June 10th, 2011 by terry. Posted under deferreds, python, twisted. | 4 Comments »

I’ve been spending a bit of time thinking again about queues and services. I wrote a Twisted class in 2009 to maintain a resizable dispatch queue (code in Launchpad, description on the Twisted mailing list). For this post I’ve pulled out (and simplified slightly) one of its helper classes, a DeferredPool.

This simple class maintains a set of deferreds and gives you a mechanism to get a deferred that will fire when (if!) the size of the set ever drops to zero. This is useful because it can be used to gracefully shut down a service that has a bunch of outstanding requests in flight. For each incoming request (that’s handled via a deferred), you add the deferred to the pool. When a signal arrives to tell the service to stop, you stop taking new requests and ask the pool for a deferred that will fire when all the outstanding deferreds are done, then you exit. This can all be done elegantly in Twisted, the last part by having the stopService method return the deferred you get back from the pool (perhaps after you add more cleanup callbacks to it).

Here’s the code:


from twisted.internet import defer

class DeferredPool(object):
    """Maintains a pool of not-yet-fired deferreds and gives a mechanism to
    request a deferred that fires when the pool size goes to zero."""

    def __init__(self):
        self._pool = set()
        self._waiting = []

    def _fired(self, result, d):
        """Callback/errback each pooled deferred runs when it fires. The
        deferred first removes itself from the pool. If the pool is then
        empty, fire all the waiting deferreds (which were returned by
        notifyWhenEmpty)."""
        self._pool.remove(d)
        if not self._pool:
            waiting, self._waiting = self._waiting, []
            for waiter in waiting:
                waiter.callback(None)
        return result

    def add(self, d):
        """Add a deferred to the pool."""
        d.addBoth(self._fired, d)
        self._pool.add(d)

    def notifyWhenEmpty(self, testImmediately=True):
        """Return a deferred that fires (with None) when the pool empties.
        If testImmediately is True and the pool is empty, return an already
        fired deferred (via succeed)."""
        if testImmediately and not self._pool:
            return defer.succeed(None)
        else:
            d = defer.Deferred()
            self._waiting.append(d)
            return d

As usual I’m posting this example because I find Twisted’s deferreds so elegant. Here are a few comments on the above that might help you understand deferreds better.

A frequent pattern when creating and managing deferreds is that you can add callbacks and errbacks to them yourself to transparently do some housekeeping when they fire. In this case, for each deferred passed to add, I’m adding a callback and an errback that will run self._fired when the deferred fires. The first thing that method does is take the deferred out of the pool of outstanding deferreds. So the deferred itself cleans up the pool. It does that transparently, by which I mean that the call/errback function (self._fired) always returns whatever result it was passed. It’s on both the callback and errback chains of the deferred and has no effect on the result. The deferred may already have call/errbacks on it when it is passed to add, and it may have them added to it after add is done. Whoever created and is otherwise using the deferred will be none the wiser and is in no way affected.

When a deferred in the pool fires, it also checks to see if the pool size is zero and if there are any deferreds waiting to be informed of that. If so, it fires all the waiting deferreds and empties the list of waiting deferreds. This doesn’t mean the action is necessarily over. More deferreds can be added, more waiters can be added, etc. The pool size can go to zero again and if there are no waiters are waiting, no big deal, etc.

It’s easy to add functionality to e.g., record what time deferreds were added, provide stats, allow outstanding deferreds to be cancelled, add notifications when high/low water marks are reached, etc. But that’s enough for now. Feel free to ask questions below.


The eighty six non-trivial powers ≤ 2^20

00:32 March 30th, 2011 by terry. Posted under other, python. | 3 Comments »

Tonight Jamu Kakar mentioned in IRC that a program of his had unexpectedly crashed after processing 1,048,376 items. I think it’s a useful debugging skill to have to be able to recognize numbers like that (it’s very close to 2^20). I’ve often wanted to write a tiny program to print out all the non-trivial powers, and since I have far more important and pressing things to be doing, I immediately went to write the code. At a minimum it seems prudent to recognize all powers up to 1000, and the powers of 2 to much higher. Below you have all 86 non-trivial powers up to 2^20. I don’t know them all, but I wish I did.

  4 = 2^2                  729 = 3^6, 9^3                32768 = 2^15, 8^5
  8 = 2^3                 1000 = 10^3                    38416 = 14^4
  9 = 3^2                 1024 = 2^10, 4^5               46656 = 6^6
 16 = 2^4, 4^2            1296 = 6^4                     50625 = 15^4
 25 = 5^2                 1331 = 11^3                    59049 = 3^10, 9^5
 27 = 3^3                 1728 = 12^3                    65536 = 2^16, 4^8, 16^4
 32 = 2^5                 2048 = 2^11                    78125 = 5^7
 36 = 6^2                 2187 = 3^7                     83521 = 17^4
 49 = 7^2                 2197 = 13^3                   100000 = 10^5
 64 = 2^6, 4^3, 8^2       2401 = 7^4                    104976 = 18^4
 81 = 3^4, 9^2            2744 = 14^3                   117649 = 7^6
100 = 10^2                3125 = 5^5                    130321 = 19^4
121 = 11^2                3375 = 15^3                   131072 = 2^17
125 = 5^3                 4096 = 2^12, 4^6, 8^4, 16^3   160000 = 20^4
128 = 2^7                 4913 = 17^3                   161051 = 11^5
144 = 12^2                5832 = 18^3                   177147 = 3^11
169 = 13^2                6561 = 3^8, 9^4               248832 = 12^5
196 = 14^2                6859 = 19^3                   262144 = 2^18, 4^9, 8^6
216 = 6^3                 7776 = 6^5                    279936 = 6^7
225 = 15^2                8000 = 20^3                   371293 = 13^5
243 = 3^5                 8192 = 2^13                   390625 = 5^8
256 = 2^8, 4^4, 16^2     10000 = 10^4                   524288 = 2^19
289 = 17^2               14641 = 11^4                   531441 = 3^12, 9^6
324 = 18^2               15625 = 5^6                    537824 = 14^5
343 = 7^3                16384 = 2^14, 4^7              759375 = 15^5
361 = 19^2               16807 = 7^5                    823543 = 7^7
400 = 20^2               19683 = 3^9                   1000000 = 10^6
512 = 2^9, 8^3           20736 = 12^4                  1048576 = 2^20, 4^10, 16^5
625 = 5^4                28561 = 13^4

I produced the above with this quick hack:


from collections import defaultdict

powers = defaultdict(list)
lim = 20

for a in range(2, lim + 1):
    for b in range(2, lim + 1):
        n = a ** b
        if n > 2 ** lim:
            break
        powers[n].append((a, b))

for n in sorted(powers.keys()):
    print '%7d = %s' % (n,
                        ', '.join('%d^%d' % (a, b)
                                  for (a, b) in powers[n]))


GMZD: Google Maps Zoom-out Distance

13:30 February 6th, 2011 by terry. Posted under other, travel. | 1 Comment »

Here’s a fun and simple measure of distance between any two locations, A and B. First, find A using Google maps and zoom in (centered) as far as you can go, though don’t go into street view as lots of places still don’t have that. Now, if you can already see B on the map, it has a Google Maps Zoom-out Distance (GMZD) of zero because you don’t need to zoom out at all to see B. If you have to zoom out once, then A and B are at distance 1 according to GMZD, etc.

For example, let’s start with Union Square in New York. Fully zoomed in we can see Coffee Shop, so that’s at distance 0. Those things are about a minute’s walk from the center of Union Square. Zooming out one click, we pick up Bowlmor Lanes on University Place and the Whole Foods Market at the South of Union Square. Those things are at GMZD-1. The outer edge of distance 1 is about a few minute’s walk from Union Square. Continuing outwards, Betaworks is at GMZD-4, Central Park at distance 6, Boston and Niagara Falls at distance 12, Florida, Winnipeg, and St John’s, Newfoundland at 14, San Francisco at 15, Barcelona at 16, and Sydney at 17. (Although you can zoom out 18 levels, GMZD-17 seems to be as many as you practically need to see anything.)

You can also think of GMZD as half the number of clicks you’d need to do on Google maps to go from being fully zoomed in on A to being fully zoomed in on B (with some panning in between). When you look at Google maps you can count the number of notches on the little slider (see image on left) above your current zoom level to see the GMZD from the center of the visible map to its outer edges.

Update: I meant to mention that GMZD is not a formal distance metric. It is non-negative (GMZD(A, B) >= 0) and symmetric (GMZD(A, B) = GMZD(B, A)) for all points A and B, but distinct points can be at distance zero and (as a result) the triangle inequality also does not hold (e.g., Union Square is distance zero from Coffee Shop, and Coffee Shop is distance zero from Union Square Cafe, but the distance from Union Square to Union Square Cafe is one. Not being a metric space is what makes it interesting, though :-)


Apple channeling Microsoft?

23:59 February 1st, 2011 by terry. Posted under companies, tech. | 10 Comments »

Image by Lara64

Apple’s behavior, as described today in the New York Times and in Ars Technica reminds me of Microsoft building MSIE into Windows. When that happened, other browser manufacturers cried foul. They argued that this was bundling, that few people would want to use a non-native browser, and that Microsoft was using its platform monopoly to tilt the browser playing field.

Here again we have a vendor (Apple), with an operating system platform (iOS), with a piece of extremely valuable functionality (the App Store) built in by the vendor, who are now strong-arming others writing applications for the platform into always offering access through their functionality. That all reminds me of Microsoft.

While it might now be difficult to think of the iPhone without the App Store, the iPhone existed for 18 months before the App Store came along: the iPhone was released in January 2007, the App Store in July 2008. Windows and MSIE also started life as independent entities; it was about 2 years before they were fused and optimistically declared inseparable.

The two cases are obviously not the same in detail, but I find the similarities striking and thought-provoking.

Just for fun, imagine a court case aimed at forcing Apple to make their App Store separable from their operating system platform. To allow others to build their own app stores. To give the user the choice to install/uninstall whatever app stores they liked. Imagine Apple claiming that such a separation is technically impossible and that the App Store is fundamental to the iPhone experience.

Couldn’t possibly happen, right?


py-narrow-to-class

00:45 January 28th, 2011 by terry. Posted under python, tech. | 9 Comments »

I can never understand when I meet programmers who don’t use emacs. As a programmer, you spend inordinate amounts of time in your editor. You call yourself a programmer. You like to automate things. You get frustrated when you can’t take matters into your own hands. You like hacking on things. Right? And so…….. why wouldn’t you be deeply attracted to an editor that is fully programmable? Sure, (emacs) lisp may not be to everyone’s liking, but being able to program your editor is hugely powerful, especially when the programming language comes with an extremely strong library of tools just for editing text inside the editor.

Jamu Kakar, another emacs fan was just over at my place. He didn’t know about narrowing the buffer – to only show one section of it so that you can edit it to your heart’s content (e.g., global search & replace) and then widen it again when you’re done. We were looking at some Python code and I did a search. The class we were looking at was long, and I didn’t know if my search had finished in code that was still part of the same class. I said to Jamu “Emacs Python mode should have a function that narrows the buffer to the current class”.

After he was gone, I was thinking about that, and realized it would be easy to write. It’s all of 8 lines.

(defun py-narrow-to-class nil
  (interactive)
  (save-excursion
    (py-beginning-of-def-or-class t)
    (let
        ((start (point)))
      (py-end-of-def-or-class t)
      (narrow-to-region (point) start))))

Not too shabby, and it took less than 5 minutes to write it. In words: here’s a function called py-narrow-to-class that takes no arguments and that I want to call interactively (via M-x py-narrow-to-class). It’s going to go to the start of the current Python class, set a local variable called start to remember that location, then move to the end of the class, and narrow the buffer. That’s wrapped in a (save-excursion) so that when all that moving around and narrowing is done, the cursor will be in the exact spot it was when I started. If I want, I can now assign this function to a single keystroke when I’m in Python mode.

If you don’t think that’s pretty neat, you’re probably not a programmer. Can you do that in your editor?


jsongrep.py – Python for extracting pieces of JSON objects

02:10 November 25th, 2010 by terry. Posted under FluidDB, python. | 18 Comments »

Lots of APIs these days return JSON objects. I love JSON, but reading a raw JSON dump can be awkward. You can print the whole thing using pprint in Python (or your favorite language), but what if you want to grep out and print only parts of the JSON? I was thinking tonight that it would be easy and useful to write a recursive script to do that. It took about half an hour to arrive at this solution:

#!/usr/bin/env python

import sys
import re
import json
from pprint import pprint

def jsongrep(d, patterns):
    try:
        pattern = patterns.pop(0)
    except IndexError:
        pprint(d)
    else:
        if isinstance(d, dict):
            keys = filter(pattern.match, d.keys())
        elif isinstance(d, list):
            keys = map(int,
                       filter(pattern.match,
                              ['%d' % i for i in range(len(d))]))
        else:
            if pattern.match(str(d)):
                pprint(d)
            return
        for item in (d[key] for key in keys):
            jsongrep(item, patterns[:])

if __name__ == '__main__':
    try:
        j = json.loads(sys.stdin.read())
    except ValueError, e:
        print >>sys.stderr, 'Could not load JSON object from stdin.'
        sys.exit(1)

    jsongrep(j, map(re.compile, sys.argv[1:]))

Usage is really simple. Let’s look at a couple of easy examples from the command line:

$ echo '{"hey" : "you"}' | jsongrep.py hey
u'you'

jsongrep.py has matched the “hey” key in the JSON object and printed its value. Let’s do the same thing with a 2-level JSON object:

$ echo '{"hey" : { "there" : "you"}}' | jsongrep.py hey 
{u'there': u'you'}

Again, we see the entire object corresponding to the “hey” key. We can add another argument to drill down into the object

$ echo '{"hey" : { "there" : "you"}}' | jsongrep.py hey there
u'you'

As you might hope, you can use a regular expression for an argument:

$ echo '{"hey" : { "there" : "you"}}' | jsongrep.py 'h.*' '.*'
u'you'

which in this case could have been given more concisely as

$ echo '{"hey" : { "there" : "you"}}' | jsongrep.py h .
u'you'

So you can drill down into nested dictionaries quite easily. When jsongrep.py runs out of patterns it just prints whatever’s left. A special case of this is if you give no patterns at all, you get the whole JSON object:

$ echo '{"hey" : { "there" : "you"}}' | jsongrep.py
{u'hey': {u'there': u'you'}}

The regex patterns you pass on the command line are being matched against the keys of JSON objects (Python dicts). If jsongrep.py runs into a list, it will instead match against the list indices like so:

$ echo '{"hey" : { "joe" : ["blow", "xxx" ]}}' | jsongrep.py hey joe 1
u'xxx'

You can see we’ve pulled out just the first list element after matching “hey” and “joe”. So jsongrep.py regex args can be used to navigate your way through both JSON objects and lists.

Now let’s do something more interesting.

Twitter’s API can give you JSON, and the JSON is pretty chunky. For example, if I get my first 100 followers with this command:

curl 'http://api.twitter.com/1/statuses/followers.json?screen_name=terrycojones'

there’s 164Kb of output (try it and see). What if I just want the Twitter user names of the people who follow me? Looking at the JSON, I can see it starts with:

[{"profile_background_color":"131516","description":null

Hmm… looks like it’s a list of dictionaries. Let’s print just the first dictionary in the list:

curl 'http://api.twitter.com/1/statuses/followers.json?screen_name=terrycojones' |
jsongrep.py 0

which starts out:

{u'contributors_enabled': False,
 u'created_at': u'Wed Jul 19 00:29:58 +0000 2006',
 u'description': None,
 u'favourites_count': 0,
 u'follow_request_sent': False,
 u'followers_count': 178,
 u'following': False,
 u'friends_count': 67,
 u'geo_enabled': False,
 u'id': 2471,
 u'id_str': u'2471',
 u'lang': u'en',
 u'listed_count': 3,
 u'location': None,
 u'name': u'Roy',
 u'notifications': False,
 u'profile_background_color': u'131516',
 u'profile_background_image_url': u'http://s.twimg.com/a/1288470193/images/themes/theme14/bg.gif',
 u'profile_background_tile': True,
 u'profile_image_url': u'http://a3.twimg.com/profile_images/194788727/roy_with_phone_normal.jpg',
 u'profile_link_color': u'009999',
 u'profile_sidebar_border_color': u'eeeeee',
 u'profile_sidebar_fill_color': u'efefef',
 u'profile_text_color': u'333333',
 u'profile_use_background_image': True,
 u'protected': False,
 u'screen_name': u'wasroykosuge',

and you can see a “screen_name” key in there which looks like what we want. Let’s see the first few:

$ curl 'http://api.twitter.com/1/statuses/followers.json?screen_name=terrycojones' |
jsongrep.py . screen_name | head
u'wasroykosuge'
u'Piiiu_piiiu'
u'350'
u'KardioFit'
u'jrecursive'
u'doodlesockingad'
u'revinprogress'
u'cloudjobs'
u'PointGcomics'
u'lucasbuchala'

Finally, here’s an example using FluidDB‘s new /values HTTP call. I’ll ask FluidDB for all objects matching the query has unionsquareventures.com/portfolio and from those matching objects I’ll pull back the value of the FluidDB tag named fluiddb/about. The result is JSON that starts out like this:

{"results": { "id" : {"93989942-b519-49b4-87de-ac834e6a6161": {"fluiddb/about": {"value": "http://www.outside.in"}}

You can see there’s a 5-level deep nesting of JSON objects. I just want the “value” key on all matching objects. Easy:

curl 'http://fluiddb.fluidinfo.com/values?query=has%20unionsquareventures.com/portfolio&tag=fluiddb/about' |
jsongrep.py results . . fluiddb/about value | sort
u'http://amee.cc'
u'http://getglue.com'
u'http://stackoverflow.com'
u'http://tumblr.com'
u'http://www.10gen.com'
u'http://www.boxee.tv'
u'http://www.buglabs.net'
u'http://www.clickable.com'
u'http://www.cv.im'
u'http://www.disqus.com'
u'http://www.etsy.com'
u'http://www.flurry.com'
u'http://www.foursquare.com'
u'http://www.heyzap.com'
u'http://www.indeed.com'
u'http://www.meetup.com'
u'http://www.oddcast.com'
u'http://www.outside.in'
u'http://www.returnpath.net'
u'http://www.shapeways.com'
u'http://www.simulmedia.com'
u'http://www.targetspot.com'
u'http://www.tastylabs.com'
u'http://www.tracked.com'
u'http://www.twilio.com'
u'http://www.twitter.com'
u'http://www.workmarket.com'
u'http://www.zemanta.com'
u'http://zynga.com'

And there you have it, a sorted list of all Union Square Ventures portfolio companies, from the command line, as listed here.

jsongrep.py will also try to match on things that are not objects or lists if it runs into them, so we can refine this list a little. E.g.,

curl 'http://fluiddb.fluidinfo.com/values?query=has%20unionsquareventures.com/portfolio&tag=fluiddb/about' |
jsongrep.py results . . fluiddb/about value '.*ee' | sort
u'http://www.meetup.com'
u'http://amee.cc'
u'http://www.indeed.com'
u'http://www.boxee.tv'

being the USV companies with “ee” somewhere in their URL. Or, for some advanced regex fun, the USV companies whose URLs don’t end in “.com”:

curl 'http://fluiddb.fluidinfo.com/values?query=has%20unionsquareventures.com/portfolio&tag=fluiddb/about' |
jsongrep.py results . . fluiddb/about value '.*(?


Faulkner on splendid failure

17:02 September 29th, 2010 by terry. Posted under books, companies, Faulkner. | 4 Comments »

I always enjoy running across writing that is not about entrepreneurialism but which seems directly relevant. A couple of snippets that I’ve blogged before are The entrepreneurial spirit in literature (from Conrad‘s Heart of Darkness) and Orwell on T. S. Eliot and the path from existential angst to serial entrepreneur.

Here’s another. It’s Faulkner’s address upon receiving the National Book Award for fiction in 1955. Taken from William Faulkner Essays, Speeches & Public Letters. Random House 1965, pp 143-5.

It makes me think about what I consider Faulkner’s crowning masterpiece, Absalom, Absalom! and the effort that must have gone into its creation. It also puts me in mind of Tim O’Reilly’s exhortation to entrepreneurs to “work on stuff that matters”.

Here it is:

By artist I mean of course everyone who has tried to create something which was not here before him, with no other tools and material than the uncommerciable ones of the human spirit; who has tried to carve, no matter how crudely, on the wall of that final oblivion beyond which he will have to pass, in the tongue of the human spirit ‘Kilroy was here.’

That is primarily, and I think in its essence, all that we ever really tried to do. And I believe we will all agree that we failed. That what we made never quite matched and never will match the shape, the dream of perfection which we inherited and which drove us and will continue to drive us, even after each failure, until anguish frees us and the hand falls still at last.

Maybe it’s just as well that we are doomed to fail, since, as long as we do fail and the hand continues to hold blood, we will try again; where, if we ever did attain the dream, match the shape, scale that ultimate peak of perfection, nothing would remain but to jump off the other side of it into suicide. Which would not only deprive us of our American right to existence, not only inalienable but harmless too, since by our standards, in our culture, the pursuit of art is a peaceful hobby like breeding Dalmations, it would leave refuse in the form of, at best indigence and at worst downright crime resulting from unexhausted energy, to be scavenged and removed and disposed of. While this way, constantly and steadily occupied by, obsessed with, immersed in trying to do the impossible, faced always with the failure which we decline to recognize and accept, we stay out of trouble, keep out of the way of the practical and busy people who carry the burden of America.

So all are happy—the giants of industry and commerce, and the manipulators for profit or power of the mass emotions called government, who carry the tremendous load of geopolitical solvency, the two of which conjoined are America; and the harmless breeders of the spotted dogs (unharmed too, protected, immune in the inalienable right to exhibit our dogs to one another for acclaim, and even to the public too; defended in our right to collect from them at the rate of five or ten dollars for the special signed editions, and even at the rate of thousands to special fanciers named Picasso or Matisse).

Then something like this happens—like this, here, this afternoon; not just once and not even just once a year. Then that anguished breeder discovers that not only his fellow breeders, who must support their mutual vocation in a sort of mutual desperate defensive confederation, but other people, people whom he had considered outsiders, also hold that what he is doing is valid. And not only scattered individuals who hold his doings valid, but enough of them to confederate in their turn, for no mutual benefit of profit or defense but simply because they also believe it is not only valid but important that man should write on the wall ‘Man was here also A.D. 1953, or ’54 or ’55’, and so go on record like this this afternoon.

To tell not the individual artist but the world, the time itself, that what he did is valid. That even failure is worth while and admirable, provided only that the failure is splendid enough, the dream splendid enough, unattainable enough yet forever valuable enough, since it was of perfection.

So when this happens to him (or to one of his fellows; it doesn’t matter which one, since all share the validation of the mutual devotion) the thought occurs that perhaps one of the things wrong with our country is success. That there is too much success in it. Success is too easy. In our country a young man can gain it with no more than a little industry. He can gain it so quickly and easily that he has not had time to learn the humility to handle it with, or even to discover, realise, that he will need humility.


The first empirical evidence that confusion might be recursive

00:01 September 13th, 2010 by terry. Posted under me. | Comments Off on The first empirical evidence that confusion might be recursive

I spent 4 wonderful years (92-96) at the Santa Fe Institute in New Mexico. During that time there was a very funny underground SFI newsletter “The New Can” (a play on the name of the NM newspaper The New Mexican) that poked merciless fun at various Institute activities and researchers. The author, a brilliant friend, must unfortunately remain anonymous. I still have half a dozen copies, and I imagine I must be one of the few people on earth who does. I ran across them tonight. Below is a graph that appeared in the September 14, 1992 edition entitled “Mutation Rocks Halls of SFI”. I’ve always loved it.


Vigilante

08:48 September 3rd, 2010 by terry. Posted under me. | Comments Off on Vigilante

From terry Thu Jun 7 01:26:35 +0200 2001
To: dsmith@cs.unm.edu, high@hci.ucsd.edu

today i saw a bag snatching
happened about 20/30 yards in front of me
2 guys on a motorbike
the back guy leans sideways
smooth as can be
takes the handle of a bag from an old well dressed woman

they head off down the side of the church
right next to where i live

the people yell out to the people at the end of the street
looking away from me

i am in motion

sprinting.

i zoom past the robbed
going absolutely flat out
heading to the end of the street
thinking i had no chance at all

but, around the corner
not more than 5 yards
i see the guys on the motorbike
caught behind some walking other people
(there is construction there
which makes it narrower
harder to pass)

this is right on the corner of paseo del borne (our street)
and montcada

and…………………..

i fucking tackled them
yeah
over the top
arms spread to get them both at once
guys to the ground
motorbike to the ground
me falling stepping over the top
grazed shin, no more

i wasn’t thinking really
just knew i had to stop them
couldn’t do it as good as it could have been
and as it was the bike crashed down almost
into some people beside it
who had no clue what the fuck was going on

the guys jumped up
yelled
ripped off their helmets and flung them away
one smacking hard into the wall
and sprinted off
leaving one shoe behind

i was pretty surprised
didn’t occur to me that the bike was stolen too

the cops turned up in about a minute flat
there were 30 or 40 people gathered around
talking like crazy
no-one knew what had happened
the robbed people just came around the corner to find a mess
one guy saw it and one woman
the woman acted like my PR agent
telling the entire crowd
over and over that i was a hero

it was great
so funny
i smiled and bowed to them all
like an idiot
hamming it up

the robbed people thrust a 2000 ptas reward into my hands
absolutely insisted that i take it
(we ate it in pizza later)

the cops shrugged it off
called in the stolen bike

it was pretty cool
i could get into being a vigilante

i should have tried to have held one of the guys
but i thought hitting them hard sideways
and knocking their bike over would do it

but, it wasn’t their bike

i was smiling afterwards
the most exercise i’ve had
since beating derek to the office on skates a few weeks back


Twisted’s Deferred class chainDeferred method is too simplistic?

02:25 August 14th, 2010 by terry. Posted under deferreds, python, twisted. | 1 Comment »

I think it’s worth spending some time thinking about whether chainDeferred in twisted.internet.defer.Deferred is too simplistic. I’ve thought for a while that it could be more helpful in preventing people from doing unintended things and/or cause fewer surprises (e.g., see point #1 in this post).

Those are smaller things that people can obviously live with. But a more important one concerns deferred cancellation. See uncalled.py below for why.

Here are five examples of chainDeferred behavior that I think could be better. In an attempt to fix these, I made a few changes to a copy of defer.py (immodestly called tdefer.py, sorry) which you can grab, with runnable examples, here. The tdefer.py code is meant as a suggested approach. I doubt that it’s bulletproof.

Here are the examples.

boom1.py:

# Normal deferreds: this raises defer.AlreadyCalledError because
# the callback of d1 causes the callback of d2 to be called, but d2 has
# already been cancelled (and hence called).

# With tdefer.py: there is no error because d1.callback will not call
# d2 as it has already been cancelled.

def printCancel(fail):
    fail.trap(defer.CancelledError)
    print 'cancelled'

def canceller(d):
    print 'cancelling'

d1 = defer.Deferred()
d2 = defer.Deferred(canceller)
d2.addErrback(printCancel)
d1.chainDeferred(d2)
d2.cancel()
d1.callback('hey')

boom2.py:

# Normally: raises defer.AlreadyCalledError because calling d1.callback
# will call d2, which has already been called.

# With tdefer.py: Raises AssertionError: "Can't callback an already
# chained deferred" because calling callback on a deferred that's
# already been chained is asking for trouble (as above).

d1 = defer.Deferred()
d2 = defer.Deferred()
d1.chainDeferred(d2)
d2.callback('hey')
d1.callback('jude')

uncalled.py:

# Normally: although d2 has been chained to d1, when d1 is cancelled,
# d2's cancel method is never called. Even calling d2.cancel ourselves
# after the call to d1.cancel has no effect, as d2 has already been
# called.

# With tdefer: both cancel1 and cancel2 are called when d1.cancel is
# called. The additional final call to d2.cancel correctly has no
# effect as d2 has been called (via d1.cancel).

def cancel1(d):
    print 'cancel one'

def cancel2(d):
    print 'cancel two'

def reportCancel(fail, which):
    fail.trap(defer.CancelledError)
    print 'cancelled', which

d1 = defer.Deferred(cancel1)
d1.addErrback(reportCancel, 'one')
d2 = defer.Deferred(cancel2)
d2.addErrback(reportCancel, 'two')
d1.chainDeferred(d2)
d1.cancel()
d2.cancel()

unexpected1.py:

# Normally: prints "called: None", instead of the probably expected
# "called: hey"

# tdefer.py: prints "called: hey"

def called(result):
    print 'called:', result

d1 = defer.Deferred()
d2 = defer.Deferred()
d1.chainDeferred(d2)
d1.addCallback(called)
d1.callback('hey')

unexpected2.py:

# Normally: prints
#   called 2: hey
#   called 3: None

# tdefer.py: prints
#   called 2: hey
#   called 3: hey

def report2(result):
    print 'called 2:', result

def report3(result):
    print 'called 3:', result

d1 = defer.Deferred()
d2 = defer.Deferred().addCallback(report2)
d3 = defer.Deferred().addCallback(report3)
d1.chainDeferred(d2)
d1.chainDeferred(d3)
d1.callback('hey')

I wont go into detail here as this post is already long enough. Those are 3 classes of behavior arising from chainDeferred being very simplistic. Comments welcome, of course. Once again, the runnable code is here.


Eleanor Roosevelt

02:22 July 31st, 2010 by terry. Posted under books. | Comments Off on Eleanor Roosevelt

To read of Eleanor and Franklin is to weep at what we have lost. Gone is the ancient American sense that whatever is wrong with human society can be put right by human action. Eleanor never stopped believing this. A simple faith, no doubt simplistic – but it gave her a stoic serenity. On the funeral train from Georgia to Washington: “I lay in my berth all night with the window shade up, looking out at the countryside he had loved and watching the faces of the people at stations, and even at the crossroads, who came to pay their last tribute all through the night. The only recollection I clearly have is thinking about ‘The Lonesome Train,’ the musical poem about Lincoln’s death. (‘A lonesome train on a lonesome track/Seven coaches painted black/A slow train, a quiet train/Carrying Lincoln home again…’). I had always liked it so well – and now this was so much like it.”

I had other thoughts in 1962 at Hyde Park as I stood alongside the thirty-third, the thirty-fourth, the thirty-fifth, and the thirty-sixth Presidents of the United States, not to mention all the remaining figures of the Roosevelt era who had assembled for her funeral (unlike the golden figures in Proust’s last chapter, they all looked if not smaller than life smaller than legend – so many shrunken March of Time dolls soon to be put away). Whether or not one thought of Eleanor Roosevelt as a world ombudsman or as a chronic explainer or as a scourge of the selfish, she was like no one else in her usefulness. As the box containing her went past me, I thought, well, that’s that. We’re really on our own now.

The above are the last 2 paragraphs of Gore Vidal’s November 18, 1971 essay “Eleanor Roosevelt”. NY Review of Books.


Asynchronous data structures with Twisted Deferreds

23:55 July 23rd, 2010 by terry. Posted under deferreds, me, python, twisted. | 8 Comments »

Earlier this week I gave a talk titled Deferred Gratification (slides) at EuroPython in Birmingham. The title was supposed to hint at how much I love Twisted‘s Deferred class, and that it took me some time to really appreciate it.

While thinking about Deferreds in the days before the talk, I think I put my finger on one of the reasons I find Deferreds so attractive and elegant. The thought can be neatly summarized: Deferreds let you replace synchronous data structures with elegant asynchronous ones.

There are various ways that people get exposed to thinking about programming in an asynchronous style. The great majority do so via building user interfaces, usually with widget libraries wherein one specifies widgets and layouts, sets up event handlers, and then surrenders control to a main loop that thereafter routes events to handlers. Exposure to asynchronous programming via building UIs is becoming much more common as Javascript programmers build client-side web apps that operate asynchronously with web servers (and the “A” in AJAX of course stands for asynchronous). Others become aware of asynchronous programming via writing network code (perhaps using Twisted). Relatively few become aware of asynchronous programming via doing async filesystem I/O.

Because Twisted’s Deferreds don’t have anything to do with UIs or networking or filesystems, you can use them to implement other asynchronous things, like an asynchronous data structure. To show you what I mean, here’s a slightly simplified version of Twisted’s DeferredQueue class, taken from twisted/internet/defer.py:

class DeferredQueue(object):

    def __init__(self):
        # It would be better if these both used collections.deque (see comments section below).
        self.waiting = [] # Deferreds that are expecting an object
        self.pending = [] # Objects queued to go out via get.

    def put(self, obj):
        if self.waiting:
            self.waiting.pop(0).callback(obj)
        else:
            self.pending.append(obj)

    def get(self):
        if self.pending:
            return succeed(self.pending.pop(0))
        else:
            d = Deferred()
            self.waiting.append(d)
            return d

I find this extremely elegant, and I’m going to explain why.

But first, think about code for a regular synchronous queue. What happens if you call get on a regular queue that’s empty? Almost certainly one of two things: you’ll get some kind of QueueEmpty error, or else your code will block until some other code puts something into the queue. I.e., you either get a synchronous error or you get a synchronous non-empty response.

If you look at the get method in the code above, you’ll see that if the queue is empty (i.e., the pending list is empty), a new Deferred is made, added to self.waiting, and is immediately returned to the caller. So code calling get on an empty queue doesn’t get an error and doesn’t block, it always gets a result back essentially immediately. How can you get a result from an empty queue? Easy: the result is a Deferred. And because we’re in the asynchronous world, you just attach callbacks (like event handlers in the UI world) to the Deferred, and go on your merry way.

If you can follow that thinking, the rest of the code in the class above should be easy to grok. In put, if there are any outstanding Deferreds (i.e., earlier callers who hit an empty queue and got a Deferred back), the incoming object is given to the first of these by passing it to the callback function of the Deferred (and popping it out of the waiting list). If there are no outstanding Deferreds expecting a result, the incoming object is simply appended to self.pending. On the get side, if the queue (i.e., self.pending) is non-empty, the code creates a Deferred that has already been fired (using the succeed helper function) and returns it.

By now, this kind of code seems routine and straightforward to me. But it certainly wasn’t always that way. So if the above seems cryptic or abstract, I encourage you to think it over, maybe write some code, ask questions below, etc. To my mind, these kinds of constructs – simple, elegant, robust, practical, obviously(?) bug-free, single-threaded, etc. – are extremely instructive. You too can solve potentially gnarly (at least in the threaded world) networking coding challenges in very simple ways just by building code out of simple Twisted Deferreds (there’s nothing special about the DeferredQueue class, it’s just built using primitive Deferreds).

For extra points, think about the concept of asynchronous data structures. I find that concept very attractive, and putting my finger on it helped me to see part of the reason why I think Deferreds are so great. (In fact, as you can see from the use of succeed, Deferreds are not specifically asynchronous or synchronous: they’re so simple they don’t even care, and as a consumer of Deferreds, your code doesn’t have to either). That’s all remarkably elegant.

I sometimes hope O’Reilly will publish a second volume of Beautiful Code and ask me to write a chapter. I know exactly what I’d write about :-)