diff --git a/lib/mako/codegen.py b/lib/mako/codegen.py
index 56b0048834de5c5f396e9c100e3efcc77b144128..12bc424b8120b5a43554cb571b4d575fcaf9b3da 100644
--- a/lib/mako/codegen.py
+++ b/lib/mako/codegen.py
@@ -7,6 +7,7 @@
 """provides the Compiler object for generating module source code."""
 
 import time
+import re
 from mako.pygen import PythonPrinter
 from mako import util, ast, parsetree
 
@@ -17,7 +18,7 @@ class Compiler(object):
         self.node = node
         self.filename = filename
     def render(self):
-        buf = util.StringIO()
+        buf = util.FastEncodingBuffer()
         printer = PythonPrinter(buf)
         
         # module-level names, python code
diff --git a/lib/mako/template.py b/lib/mako/template.py
index 562495d40099026d68f5bf33042699d68e6304f9..d6e40d33ac6744f7bfd0afbebcfae19e5157851a 100644
--- a/lib/mako/template.py
+++ b/lib/mako/template.py
@@ -23,7 +23,7 @@ class _ModuleMarker(object):
 
 class Template(object):
     """a compiled template"""
-    def __init__(self, text=None, module=None, identifier=None, filename=None, format_exceptions=True, error_handler=None, lookup=None):
+    def __init__(self, text=None, module=None, identifier=None, filename=None, format_exceptions=False, error_handler=None, lookup=None, output_encoding=None):
         """construct a new Template instance using either literal template text, or a previously loaded template module
         
         text - textual template source, or None if a module is to be provided
@@ -53,6 +53,7 @@ class Template(object):
         self.format_exceptions = format_exceptions
         self.error_handler = error_handler
         self.lookup = lookup
+        self.output_encoding = output_encoding
         _modules[module.__name__] = _ModuleMarker(module)
 
     source = property(lambda self:_get_template_source(self.callable_), doc="""return the template source code for this Template.""")
@@ -61,11 +62,17 @@ class Template(object):
     def render(self, *args, **data):
         """render the output of this template as a string.
         
+        if the template specifies an output encoding, the string will be encoded accordingly, else the output
+        is raw (raw output uses cStringIO and can't handle multibyte characters).
         a Context object is created corresponding to the given data.  Arguments that are explictly
         declared by this template's internal rendering method are also pulled from the given *args, **data 
         members."""
-        return _render(self, self.callable_, *args, **data)
+        return _render(self, self.callable_, args, data)
     
+    def render_unicode(self, *args, **data):
+        """render the output of this template as a unicode object."""
+        return _render(self, self.callable_, args, data, as_unicode=True)
+        
     def render_context(self, context, *args, **kwargs):
         """render this Template with the given context.  
         
@@ -93,10 +100,15 @@ def _compile_text(text, identifier, filename):
     code = compile(source, filename or cid, 'exec')
     exec code in module.__dict__, module.__dict__
     return (source, module)
-    
-def _render(template, callable_, *args, **data):
+
+def _render(template, callable_, args, data, as_unicode=False):
     """given a Template and a callable_ from that template, create a Context and return the string output."""
-    buf = util.StringIO()
+    if as_unicode:
+        buf = util.FastEncodingBuffer()
+    elif template.output_encoding:
+        buf = util.FastEncodingBuffer(template.output_encoding)
+    else:
+        buf = util.StringIO()
     context = Context(template, buf, **data)
     kwargs = {}
     argspec = inspect.getargspec(callable_)
diff --git a/lib/mako/util.py b/lib/mako/util.py
index 1d665fd93e24a1698024e8def14136f6c6147a34..0560d8add4afb2746e2624b13d5fcab5717b69c2 100644
--- a/lib/mako/util.py
+++ b/lib/mako/util.py
@@ -13,6 +13,19 @@ except:
 try:
     from cStringIO import StringIO
 except:
-    from StringIO import StringIO
-    
+   from StringIO import StringIO
+
+
+class FastEncodingBuffer(object):
+    """a very rudimentary buffer that is faster than StringIO, but doesnt crash on unicode data like cStringIO."""
+    def __init__(self, encoding=None):
+        self.data = []
+        self.encoding = encoding
+    def write(self, text):
+        self.data.append(text)
+    def getvalue(self):
+        if self.encoding:
+            return u''.join(self.data).encode(self.encoding)
+        else:
+            return u''.join(self.data)
 
diff --git a/test/component.py b/test/component.py
index f265b8509e75c9942563cfeaf6d0a1ba8142623b..834e3cc58d3f73b65bc2422a2fb447892f5173e2 100644
--- a/test/component.py
+++ b/test/component.py
@@ -13,6 +13,7 @@ class ComponentTest(unittest.TestCase):
         </%component>
         
         """)
+        print template.code
         assert template.render(variable='hi').strip() == """hello mycomp hi"""
 
     def test_component_blankargs(self):
diff --git a/test/template.py b/test/template.py
new file mode 100644
index 0000000000000000000000000000000000000000..c7aa5e58f987634715f34c50f9c6599a434527e1
--- /dev/null
+++ b/test/template.py
@@ -0,0 +1,18 @@
+# -*- encoding: utf-8 -*-
+
+from mako.template import Template
+import unittest
+from util import flatten_result
+
+class EncodingTest(unittest.TestCase):
+    def test_unicode(self):
+        template = Template(u"""Alors vous imaginez ma surprise, au lever du jour, quand une drôle de petit voix m’a réveillé. Elle disait: « S’il vous plaît… dessine-moi un mouton! »""")
+        assert template.render_unicode() == u"""Alors vous imaginez ma surprise, au lever du jour, quand une drôle de petit voix m’a réveillé. Elle disait: « S’il vous plaît… dessine-moi un mouton! »"""
+        
+    def test_unicode_arg(self):
+        val = u"""Alors vous imaginez ma surprise, au lever du jour, quand une drôle de petit voix m’a réveillé. Elle disait: « S’il vous plaît… dessine-moi un mouton! »"""
+        template = Template("${val}")
+        assert template.render_unicode(val=val) == u"""Alors vous imaginez ma surprise, au lever du jour, quand une drôle de petit voix m’a réveillé. Elle disait: « S’il vous plaît… dessine-moi un mouton! »"""
+        
+if __name__ == '__main__':
+    unittest.main()