Cheetah
Cheetah is a Python-powered template language, created in 2001 for the Webware for Python project, that compiles templates into Python classes rather than interpreting them - a design its developers credited with a decisive speed advantage over the search-and-replace engines of the day, and one that kept it alive as a code generator long after web templating moved on.
Created by Tavis Rudd, with Mike Orr, Chuck Esterbrook and Ian Bicking as core developers; maintained since 2017 by Oleg Broytman
Cheetah is a template engine and code-generation tool for Python, first released in June 2001. Its defining idea is simple and, for its era, unusual: a Cheetah template is not interpreted at render time but compiled into Python source code, and the resulting module defines a class. Rendering a page means instantiating that class and calling a method on it. Templates can therefore inherit from one another, be subclassed by hand-written Python, and be shipped as ordinary .py files. Its authors credited that choice with a large speed advantage over the search-and-replace engines it competed with in the pre-framework era of Python web development - a claim made in their own accounts rather than in any published benchmark - and it is why the engine outlived its own web-templating niche as a general-purpose text generator.
History and Origins
Cheetah grew directly out of Webware for Python, an application-server project that in 2000 and 2001 occupied roughly the position Django and Flask would later fill. Webware needed a template layer, and the options available were unsatisfying: mostly search-and-replace engines modelled on PHPLib’s Template class, which scanned template text for markers and substituted strings.
Two people on the webware-discuss mailing list were working on the problem independently. Mike Orr had written a PHPLib-derived engine called PlowPlate. Tavis Rudd, a freelance programmer in Vancouver, had a different design in mind. They met on May 12, 2001 - the project’s own history page places the meeting at a gelato shop on Denman Street - where Rudd sketched his outline. The idea that carried the day was compilation. As Orr later put it in the project’s history, he had thought the idea was stupid, “but it turned out that this not-so-stupid idea blew all the others out of the water in terms of performance” - a recollection of how the engines compared at the time, not a measured result against a stated baseline.
The first release came in June 2001. Over the following months the language acquired the display-logic directives it is known for: #for, #if, #echo, #set and their siblings. Rudd pushed for them from near the beginning. Orr, on his own account, initially argued against them - a template language that grows control flow risks becoming a second, worse programming language, or in his words DTML hell - and came round; the case for them, made most directly by Esterbrook, was that the people maintaining templates were often not the people writing the Python behind them and needed to express repetition and conditionals without leaving the file. A late-binding rewrite in the fall of 2001 settled the semantics, and the project’s history records that syntax and behaviour have been broadly stable ever since.
Chuck Esterbrook (Webware’s author), Ian Bicking (later of virtualenv, WebOb and Paste) and Edmund Lian were among the other core contributors. A 1.0 release was planned for January 2002 and deliberately postponed so the engine could accumulate real-world use first; a paper by Rudd, Orr and Bicking written for the Python 10 conference in February 2002 introduced it to a wider audience while it was still nominally beta, its authors noting that as of December 2001 Cheetah was beta software already used in several production applications.
Design Philosophy
The Cheetah documentation states its principles fairly explicitly, and they explain most of the language’s shape:
- Python for the back end, Cheetah for the front end. Cheetah is not meant to replace Python; it is meant to be the thin layer where content and design meet, with the real logic living in Python modules.
- The core syntax should be learnable by non-programmers. Placeholders are
$name; directives start with#. There is no XML-ish tag soup to type. - A compiled template is a Python class. This is the load-bearing decision. It gives templates inheritance, method overriding, and a normal object interface usable from Python and from other templates.
- Full access to Python from the template. Any module, object, function or data structure the surrounding program can reach, a template can reach.
- Separation and integration are both easy. Content, design and program code can be kept apart, but combining them should not require ceremony.
The trade-off in that last pair is the one Cheetah is most often criticised for. Because templates have unrestricted access to Python, nothing structurally prevents business logic from migrating into them. Later engines - Jinja2 most prominently - deliberately restricted what a template may evaluate, treating the sandbox as a feature. Cheetah belongs to the earlier school that trusted the template author.
Syntax and Key Features
Cheetah’s surface is small enough to summarise in a page.
Placeholders use $, with dotted lookups and optional braces for disambiguation:
Hello, $name!
Client: ${client.surname}, ${client.firstName}
Lookups go through a mechanism the project calls NameMapper, which unifies attribute access, dictionary access and callable invocation: $a.b.c will find a['b'] or a.b, and will call c if it is a method taking no arguments. A C implementation of NameMapper is available for speed, with a pure-Python fallback; the 2001 Python 10 paper reported the C version as up to six times faster than the pure-Python one on NameMapper lookups, while noting that against plain Python syntax the difference is negligible in real-world scenarios.
Directives use #, and cover control flow, definition and inclusion:
#for $client in $clients
#if $client.active
<li>$client.surname</li>
#end if
#end for
#set $total = len($clients)
#include "header.tmpl"
#extends BasePage
#def sidebar
...
#end def
#extends and #def are where the compile-to-class design surfaces in the language itself: a template can extend another template, override its methods, and be extended in turn by a Python class. Webware servlets historically subclassed compiled templates directly.
Other notable capabilities:
| Feature | Description |
|---|---|
Compilation to .py | The cheetah compile command turns .tmpl files into importable Python modules that can be shipped without the templates |
| Caching | Placeholders and blocks can be marked cached, with optional refresh intervals, using $*var and #cache |
| Output filters | Pluggable filters transform placeholder output - HTML escaping, for example - without touching the template body |
| Format-agnostic | Nothing in the engine assumes HTML; Cheetah is routinely used for SQL, XML, LaTeX, PostScript, email and source code |
| Error handling | #errorCatcher lets a template define what happens when a placeholder lookup fails |
Evolution
The version history divides cleanly into three eras.
The original line (2001-2010). Version 1.0 reached PyPI on January 26, 2006, four years later than planned. Cheetah 2.0 arrived in 2007, reportedly that autumn, followed by 2.0.1 shortly after, consolidating a long series of release candidates and fixing exception handling in the C NameMapper. The 2.4.x series ran through 2009 and 2010, ending with 2.4.4 on December 13, 2010. Then the project stopped.
The gap (2010-2017). The dormancy coincided almost exactly with the Python 3 transition and with the rise of Jinja2 and Mako. Cheetah 2.x was Python 2 only, and for projects planning a Python 3 migration that made it a liability. Downstream users began moving; Ettus Research’s USRP Hardware Driver, which used Cheetah to generate C++ from register descriptions, announced its switch to Mako in July 2015 for exactly these reasons - the project looked inactive and was not Python 3 compatible.
Cheetah3 and CT3 (2017-present). Oleg Broytman took over maintenance and released Cheetah3 3.0.0 on May 7, 2017, dropping pre-2.7 Python and adding Python 3 support. Point releases followed steadily: 3.1.0 on March 3, 2018 added PyPy compatibility; the 3.2.x series, opening with 3.2.0 on February 6, 2019, reworked template loading and caching; 3.3.0 on October 10, 2022 came with a rename on PyPI to CT3, after PyPI’s classification of the project as “critical” imposed a two-factor-authentication requirement the maintainer preferred to sidestep. The import name in code stayed Cheetah. Version 3.4.0 shipped December 2, 2024 with Python 3.13 fixes; 3.4.0.post5, the current release, followed on November 29, 2025, and the package now declares support for Python 2.7 and 3.4 through 3.14 on both CPython and PyPy.
Note what the third era does not contain: new language features. The maintenance work is packaging, Python-version compatibility and bug fixing. The template language itself has been effectively frozen since the 2.x days.
Current Relevance
Cheetah occupies an unusual position: the software is maintained, the language is dormant. Nobody starts a new web project with it - Jinja2 won that argument decisively, and for good reasons around sandboxing, error messages and ecosystem integration. But the installed base is real and stubborn, concentrated in two places.
The first is infrastructure code generation. Cobbler’s Kickstart templating and Salt’s optional Cheetah renderer are not web pages; they are text files generated per host from shared skeletons, which is precisely what a format-agnostic compile-to-Python engine is good at. The second is long-lived internal systems at organisations that adopted Python early, where a working template layer is not worth the cost of a rewrite.
Distribution packaging - FreeBSD Ports, Debian, Ubuntu, Fedora, Gentoo - kept the engine installable through the dormant years, and continues to. The license is MIT, and development happens on GitHub under the CheetahTemplate3 organisation.
If you want to try it today, install the current package and render a template:
| |
Why It Matters
Cheetah’s historical significance is the compilation idea. In 2001, template engines in the LAMP world overwhelmingly worked by scanning text and substituting strings; treating a template as a source file for a program was not the obvious move. Its authors credited it with a marked speed advantage over the string-substitution engines of the day - by their own recollection rather than by published benchmark - and, more importantly, it made templates composable in a way string substitution cannot be - inheritance, overriding, and a template that is just another Python class in the object graph.
Most of the mainstream Python template engines that followed adopted the same architecture. Mako compiles to Python. Jinja2 compiles to Python. Django’s engine is the notable holdout, and its performance relative to the compiled engines was a recurring topic of comparison through the late 2000s. Cheetah did not invent template compilation in general, but it demonstrated it convincingly and early in Python, and the engines that displaced it kept its core mechanism while discarding its permissiveness.
It also stands as a clean case study in how open-source projects die and how they sometimes don’t. Cheetah’s six-and-a-half-year silence had a specific cause - a Python 2-only codebase at the moment the ecosystem moved to Python 3 - and its revival had an equally specific one: a single maintainer picking it up in 2017 and doing the unglamorous compatibility work, year after year, for software whose language stopped evolving two decades ago. The dependent projects that never had to rewrite are the return on that.
Timeline
Notable Uses & Legacy
Webware for Python
The application server that Cheetah was written for. Webware servlets could subclass a compiled Cheetah template directly, since compilation produces an ordinary Python class, and the two projects shared a mailing list and much of their community through the early 2000s. Cheetah's design - Python for the back end, Cheetah for the front end, with full access to Python objects from the template - is a direct response to what Webware developers wanted and could not get from the search-and-replace engines of the day.
Cobbler
The network installation and provisioning server originally developed at Red Hat uses Cheetah as its kickstart templating engine, rendering per-machine Kickstart files, PXE configuration and other text artifacts from shared templates with host-specific variables substituted in. The same Cheetah-powered templating is reportedly exposed through Cobbler's configuration-management integrations, so the templates that drive an installation can also drive the configuration files that follow it. This is Cheetah in its code-generation role rather than its web role, and it is reportedly part of why the engine remained packaged in Fedora, Debian, Ubuntu and Gentoo long after web frameworks moved to Jinja2.
Salt
Salt's configuration management system ships a Cheetah renderer - salt.renderers.cheetah, still present in the current Salt documentation - as one of its selectable template renderers alongside Jinja2, Mako, Genshi and others, letting operators write state files and managed configuration files in whichever template dialect they already know. The engine is optional rather than the default, which is characteristic of Cheetah's later life: present as a compatibility option in large infrastructure tools rather than as anyone's first choice for new work.
IronPort Systems
The email security appliance vendor, later acquired by Cisco, was among Cheetah's most-cited commercial users. Contemporary accounts describe its appliance web interfaces as built on the Aquarium framework, which tightly integrated Cheetah as its template layer; the frequently repeated figure of over a million lines of Python behind the product comes from those accounts rather than from a source that can be checked today, so treat the scale as reported rather than confirmed. What is documented is the integration itself: Aquarium's own materials note that its project lead went on to become a Cheetah co-developer.
USRP Hardware Driver (UHD)
Ettus Research's driver for USRP software-defined radios, used with GNU Radio, generated C++ register-map and interface code from Cheetah templates. In July 2015 the project proposed and carried out a move to Mako, the announcement on the USRP and GNU Radio mailing lists citing Cheetah's apparent inactivity and its lack of Python 3 compatibility, against Mako's active community and stable API - a well-documented example of both the code-generation use case Cheetah was good at and the migration pressure that built up around the stalled 2.x line. The change affected only those building UHD from source.
Linux distribution packaging
Cheetah has been packaged for FreeBSD Ports and for Gentoo, Fedora, Debian and Ubuntu, largely because system tools written in Python depended on it. Distribution packaging is the quiet form of longevity for a library like this: it kept Cheetah installable and patched through the years when upstream development had stopped entirely.
Language Influence
Influenced By
Running Today
Run examples using the official Docker image:
docker pull python:3.13-alpineExample usage:
docker run --rm -v $(pwd):/app -w /app python:3.13-alpine sh -c 'pip install --quiet CT3 && cheetah fill --stdout hello.tmpl'