Est. 2001 Beginner

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

Paradigm Template language - text with $placeholders and #directives, compiled into Python source; supports inheritance, since a compiled template is a Python class
Typing Dynamic - placeholders resolve at render time against Python objects, dictionaries and namespaces via the NameMapper lookup mechanism
First Appeared 2001 - conceived in spring 2001 on the webware-discuss mailing list, with the initial release, version 0.9.5, in June 2001
Latest Version 3.4.0.post5, published to PyPI on November 29, 2025, under the package name CT3

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:

FeatureDescription
Compilation to .pyThe cheetah compile command turns .tmpl files into importable Python modules that can be shipped without the templates
CachingPlaceholders and blocks can be marked cached, with optional refresh intervals, using $*var and #cache
Output filtersPluggable filters transform placeholder output - HTML escaping, for example - without touching the template body
Format-agnosticNothing 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:

1
2
pip install CT3
cheetah fill --stdout hello.tmpl

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

2001
Cheetah is conceived in spring 2001 out of discussions on the webware-discuss mailing list, where developers building on Webware for Python were dissatisfied with the available templating options. Mike Orr had written PlowPlate, modelled on PHPLib's Template library; Tavis Rudd was working on ideas of his own. The two met in Vancouver on May 12, 2001, where Rudd sketched out his design. The key insight, in Orr's later account, was compiling templates to Python source code instead of doing search-and-replace on the template text - an approach that, in his words, blew all the others out of the water in terms of performance. The initial release follows in June 2001
2001
Display-logic directives - #for, #if, #echo and their relatives - are added over the course of the year. Rudd pushed for them from early on; Orr initially resisted, on the grounds that a template language growing control flow would end in what he called DTML hell, and Esterbrook argued that non-programmers maintaining templates needed loops and conditionals. A late-binding rewrite in the fall of 2001 settles the core semantics; the project's own history notes that syntax and behaviour have been relatively stable ever since. The engine remains in the 0.9.x beta series through late 2001, by which point its authors describe it as already in use in several production applications
2002
A paper by Rudd, Orr and Bicking, written for the Python 10 conference (February 2002) and dated December 2001, describes Cheetah as the Python-powered template engine. A 1.0 release had been targeted for January 2002 but the team deliberately delayed it to gather more real-world usage and feedback - a decision the project's history page records explicitly
2006
Cheetah 1.0 is published to the Python Package Index on January 26, 2006, four years after the originally planned date. By this point the engine has become the default templating layer for Webware-based applications and has spread well beyond it, into command-line code generation and configuration-file rendering
2007
Cheetah 2.0 is released, reportedly in the autumn of 2007, with 2.0.1 following shortly after. The release consolidates a long run of betas and release candidates, fixes exception handling in the optional C implementation of NameMapper and corrects filtering of #included subtemplates. Like most major Cheetah releases it requires recompiling every previously compiled template
2010
Cheetah 2.4.4 is published on December 13, 2010. It proves to be the last release of the original 2.x line; the Python 2-only codebase then sits without a new upload for more than six years while Jinja2 and Mako take over most new Python web work. Downstream projects begin migrating - the USRP Hardware Driver used with GNU Radio, for instance, proposed replacing its Cheetah templates with Mako in July 2015
2017
Oleg Broytman revives the project as Cheetah3, releasing 3.0.0 on May 7, 2017. Support for Python older than 2.7 is dropped and the code is updated to run on Python 3 as well, reportedly tested against 3.3 and later at the time. Sixteen years after its first release, Cheetah finally works on Python 3. As with 2.0, all previously compiled templates must be recompiled
2018
Cheetah 3.1.0 is released on March 3, 2018, adding PyPy compatibility. Maintenance settles into a steady rhythm of point releases through the 3.2.x series, beginning with 3.2.0 on February 6, 2019, which drops Python 3.3, extends template loading to .py, .pyc and .tmpl files, and reworks caching
2022
With release 3.3.0 on October 10, 2022, the project is renamed on PyPI from Cheetah3 to CT3. Broytman's stated reason is that PyPI had classified the Cheetah3 project as critical, which imposed a mandatory two-factor-authentication burden on maintaining it; the Cheetah3 package name receives no further updates. The import name in Python code remains Cheetah
2024
CT3 3.4.0 is released on December 2, 2024, fixing import-hook and byte-code handling issues and addressing Python 3.13 compatibility. The current package metadata for the 3.4.x series declares support for Python 2.7 and for Python 3.4 through 3.14, and lists both CPython and PyPy as supported implementations
2025
3.4.0.post5 is published on November 29, 2025 - a packaging-level update rather than a language change. The template language itself has not meaningfully changed since the 2.x era: Cheetah today is a maintained implementation of a dormant language, kept running for the installed base rather than evolved for new users

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-alpine

Example usage:

docker run --rm -v $(pwd):/app -w /app python:3.13-alpine sh -c 'pip install --quiet CT3 && cheetah fill --stdout hello.tmpl'
Last updated: