Cairo is great for rendering stuff, but doesn't give you many options to export your data. The Python Image Library has good options to save stuff. The problem I ran into is that I have a ARGB32 pycairo surface, and PIL doesn't support ARGB32. It supports RGBA instead. After much experimentation, I came up with the following piece of code, using numpy to solve this problem:

def pilImageFromCairoSurface( surface ):
   cairoFormat = surface.get_format()
   if cairoFormat == cairo.FORMAT_ARGB32:
      pilMode = 'RGB'
      # Cairo has ARGB. Convert this to RGB for PIL which supports only RGB or
      # RGBA.
      argbArray = numpy.fromstring( surface.get_data(), 'c' ).reshape( -1, 4 )
      rgbArray = argbArray[ :, 2::-1 ]
      pilData = rgbArray.reshape( -1 ).tostring()
   else:
      raise ValueError( 'Unsupported cairo format: %d' % cairoFormat )
   pilImage = PIL.Image.frombuffer( pilMode,
         ( surface.get_width(), surface.get_height() ), pilData, "raw",
         pilMode, 0, 1 )
   pilImage = pilImage.convert( 'RGB' )
   return pilImage

This reportedly doesn't work with python 3, which requires the "argbArray = " line to read:

argbArray = numpy.fromstring( bytes(surface.get_data()), 'c' ).reshape( -1, 4 )
See the disqus comments below for more details.