Log <-

Archive for September, 2009

Simple function caching in Python

Tuesday, September 15th, 2009

Python dynamic nature continues to astound me. I was working on a small library when I noted it did a lot of redundant IO calls. Now I'm not one for premature optimization, but a while ago I was thinking about writing a decorator or something that would wrap around functions and methods, and cache the returns. Turns out it's way easier than I thought, and I whipped this up in a couple of minutes:

#!/usr/bin/python
#
# Public Domain.
 
__cache = {} # Global cache
 
def fncache(fn):
   """
   Function caching decorator. Keeps a cache of the return 
   value of a function and serves from cache on consecutive
   calls to the function. 
 
   Cache keys are computed from a hash of the function 
   name and the parameters (this differentiates between 
   instances through the 'self' param). Only works if 
   parameters have a unique repr() (almost everything).
 
   Example:
 
   >>> @fncache
   ... def greenham(a, b=2, c=3):
   ...   print 'CACHE MISS'
   ...   return('I like turtles')
   ... 
   >>> print greenham(1)           # Cache miss
   CACHE MISS
   I like turtles
   >>> print greenham(1)           # Cache hit
   I like turtles
   >>> print greenham(1, 2, 3)     # Cache miss (even though default params)
   CACHE MISS
   I like turtles
   >>> print greenham(2, 2, ['a']) # Cache miss
   CACHE MISS
   I like turtles
   >>> print greenham(2, 2, ['b']) # Cache miss
   CACHE MISS
   I like turtles
   >>> print greenham(2, 2, ['a']) # Cache hit
   I like turtles
   """
   def new(*args, **kwargs):
      h = hash(repr(fn) + repr(args) + repr(kwargs))
      if not h in __cache:
         __cache[h] = fn(*args, **kwargs)
      return(__cache[h])
   new.__doc__ = "%s %s" % (fn.__doc__, "(cached)")
   return(new)
 
if __name__ == '__main__':
   import doctest
   doctest.testmod()

Save to a file named 'fncache.py' and import it into your program. Then decorate your functions and methods with it, and their output will be cached. Python rocks. Remember, only use for functions that do heavy calculations, file or network IO. Determining the uniqueness of the function call is rather expensive.

HIrcd – minimal IRC server in Python

Monday, September 14th, 2009

I wrote a little IRC server in Python:

HIrcd is a minimal, hacky implementation of an IRC server daemon written in Python in about 400 lines of code, including comments, etc.

It is mostly useful as a testing tool or perhaps for building something like a private proxy on. Do NOT use it in any kind of production code or anything that will ever be connected to by the public.

Direct link to the source code, for those interested.

Software Bashing

Thursday, September 3rd, 2009

We started a new site where we can vent our rage on all things sucky about software:

Software Bashing: We hate software. With a passion:

Fact: All software sucks. We're here to show you exactly why, and just how much it truly sucks. We don't discriminate against vendor or development model; all software sucks. We are relentless. We show no mercy. If the software exists, we will find its suckage, no matter how much it leverages synergetic business potential. Be prepared.

Hopefully we can reach some software authors and make them see the light. If not, at least I was able significantly reduce my blood pressure through the site.