Lenny Domnitser’s

⇙ Jump to content


This is a static archive of the domnit.org blog,
which Lenny Domnitser wrote between 2006 and 2009.

Part 2

Washing a peanut oil stain makes two concentric peanut oil stains.

Part 1

You’ve wronged me, jar of natural peanut butter. I scoff at the partially hydrogenated oils and added sugars of your pasty cousins, but you have taken oil separation too far. I was opening you, when you spilled upon my cloth chair. Who will look at the stain you left and believe for a moment that it is anything but semen? You have soiled my name (and my furniture), and I have no recourse besides a duel. When the soapy water dries, we will see who is the better man, my cylindrical friend.

Is That Carbon in Your Copy?

Dear Media,

Carbon isn’t carbon dioxide.


Now that that’s out of the way, good on you Salon. I almost stopped reading “Earth to PETA,” then thought better, and looked up carbon sequestration. It’s supposed to be carbon—cool!

A Few URLs Tab Saver

This new Firefox extension posts all of your tabs to A Few URLs. Here’s what it looks like:

"Post All Tabs to A Few URLs" is in Firefox's Bookmarks menu

Installation instructions: clickety click.

Source code: bzr get http://domnit.org/afewurlstabs/.

Think Inside the Box

Sneeze Steve, The Great Pizza Orientation Test:

The dividing line was exactly 90 degrees up the middle, but mushrooms were on the left!

No, no, no! Try looking from the pizza’s perspective. The pepperoni is on the left, looking out at the eater.

Figure 1. Pizza’s-eye view of a crowd.

Also, The Sneeze’s new tagline should be “Left half zine. Right half blog. Bottom half not good with fractions.” Not only is it self-referential and confusing, it has innuendo from “bottom half.”

Recovering from Trolls

I love this exchange from a Reddit comment thread. Logic overcomes trolls, idiots, and grammar Nazis.

whose gay?
your gay

WikiHow > Categories > Communications> English Grammar

You’re and Your


since we’re all being conan teh grammarians, it’s also “who’s” and not “whose”.

As in: “who is gay?”


So… he got it right then?

Whose gay (is it)? (It is) your gay.

Damn you narrow tubes, I want my Radiohead

You should be able to get In Rainbows, but don’t count on that link working today.

Procs: Run Python Functions in Parallel Processes

Sixth Python post in three weeks, woo!

Python FAQ: “be creative with dividing the work up between multiple processes rather than multiple threads.”

I wrote a library that takes a list of functions and their parameters, executes them all in parallel child processes, and returns the results. It’s called procs.

Code, docs. The code is just one file, and a small one at that.

Using procs

Suppose you have parallelizable code that looks like this:

result1 = slow_function(5, 'hello', foo=3.14)
result2 = slower_function(x=10, y=3)

With procs, instead of calling it directly, you make process specifications that almost look like the call:

from procs import *
proc1 = proc(slow_function, 5, 'hello', foo=3.14)
proc2 = proc(slower_function, x=10, y=3)

Then call them:

results = call([proc1, proc2])
result1, result2 = tuple(results)

results, in the example above, is a generator that yields the results of the functions in the order they were passed to call. They are yielded as soon as they are ready, but in order. This has its upside and downside:

In the likely case that one function is called several times with different parameters, procs also provides pmap, which is a map function interface to procs calling. This will be used in the next example.

Really using procs

Let’s see how it fares on a Wide Finder benchmark. I started with Fredrik Lundh’s wf-6.py, removed more code than I added in, and got the expected slightly slower result. My laptop runs his code in about 0.64 time, negligible clock, mine in about 0.64 time, 0.01 clock. Since it’s more suited to the way procs works, I create a process for each chunk right away. For the given dataset, 4 worker processes are running on my 2 CPU cores.

In my version, all of Fredrik’s parallelization code is taken out, and replaced with:

import procs
from functools import partial
result = procs.pmap(partial(process, FILE),
                    getchunks(FILE, 50*1024*1024))

Notice how nicely functional code can be parallelized—my wide finder can be converted to a serial finder by changing the above lines to:

from functools import partial
result = map(partial(process, FILE),
                     getchunks(FILE, 50*1024*1024))

If you have some serial code like this, procs might be able to easily widen it.


Procs doesn’t handle exceptions yet. If a child process fails, it zombifies with no indication that anything went wrong.

There are probably other bugs. Please tell me.


If you are interested in procs, please email me or leave comments with bug reports, patches, and such. I don’t know enough about this problem to put out something I’d call 1.0 by myself, but if Open Source Happens, I think we could have something good.

Again: code, docs.

Update 2007-10-11: Exception handling added.

Encoded Python

PEP 263:

This PEP proposes to introduce a syntax to declare the encoding of
a Python source file. The encoding information is then used by the
Python parser to interpret the file using the given encoding.

I wonder if this will work:

#!/usr/bin/env python
# coding: rot-13

vzcbeg flf

qrs uryyb(jbeyq='World', svyr=flf.fgqbhg):
    cevag >> svyr, 'Hello', jbeyq

PNGPU = h'''Havpbqr fgevatf ner nyfb ebg-13,
ohg olgr fgevatf ner whfg olgrf, fb ner abg
rapbqrq nybat jvgu gur bgure fbhepr pbqr.'''

cevag PNGPU

Yes, you can write Python in rot-13, with one catch: strings are just bytes, so they don’t get encoded. Unicode strings are encoded with the rest of it.

That’s sufficiently murky. Next order of business is to write even more obscure code:

#!/usr/bin/env python
# coding: base64

Rats! Even though 'whatever'.encode('base64') is perfectly valid Python, this didn’t fly. Given what I saw from the rot-13 example, I was interested to see how strings would work with base64 Python. Alas, even this simplest test, just the Python pass statement, a no-op, was a syntax error.

Competent, my ass.