2014-09-26



SQLAlchemy is one of those tools that is so powerful and so well-established that it's
hard to imagine a time when it didn't exist. Mike Bayer, the project's primary author, after what
I'm sure was a lot of real-world experience, hit on the right amount of abstraction
and API that pleases both die-hard DBA types as well as more casual users.

So why would anyone use peewee?

Solving different problems

I often mentally compare SQLAlchemy with the relational database Postgresql. Postgresql comes with everything you
could want in an RDBMS, and is even adding features more commonly found in popular non-relational databases, such as the new
jsonb functions and
HStore. Postgresql is the go-to relational database in the communities I
follow (like proggit and haternews).
And likewise, SQLAlchemy is the database toolkit loved most by serious Python developers.

I also think SQLite is a fantastic database. I mention SQLite because, on the surface, it seems comparable to Postgresql. After all, they're both
relational databases.

I think the similarity ends there, though. Postgresql is intended to solve a vastly
different set of problems than SQLite. D. Richard Hipp, the author of SQLite, gave
an awesome keynote
at PGCon this year which outlines some of the differences between the libraries. Postgresql's
goal is to be the world's most advanced open-source database, while SQLite's goal is
to replace fopen(). To put it another way, Postgresql
is like a swiss army knife, with lots of neat tools for various purposes, while SQLite is
like a scalpel. SQLite has a much more limited scope, and my feeling is that it's primary
strength lies in that focus.

SQLAlchemy is, in my mind, the swiss army knife of Python ORMs. I bet SQLAlchemy can handle
any query or relational structure you want to throw at it. Additionally, the unit of work
and identity-mapper patterns provide great performance and solve some problems you might
encounter when using an active-record ORM. Being built from the bottom-up, SQLAlchemy also
provides nice APIs no matter how near or far you want to be from SQL.

Peewee, as it's name indicates, is much (much) smaller in scope. The project's goal is to
provide composable, expressive, and predictable APIs for executing SQL queries and working
with tabular data. Peewee's APIs are very close to their SQL counterparts, and there is
only a thin layer of abstraction between the ORM code you write and the generated SQL. I
think peewee is attractive to developers who already know SQL and want an unobstrusive,
Pythonic way to use a relational database. It is my hope that peewee's simplicity is also
it's strength.

Architecturally, peewee is also different from SQLAlchemy. peewee follows the active-record
pattern which is also used by the Django ORM. Transactions are managed explicitly and by
default each connection runs in autocommit mode. Like Django and SQLAlchemy, peewee uses
declarative model classes with a variety of field types
exposed as class attributes. Unlike Django, peewee uses operator overloading to create
SQL expressions, e.g. User.username == 'huey'.

Simplicity encourages hacking



My father-in-law enjoys working on cars, and among other feats of engineering, he's rebuilt
a sweet 1960's mustang (painted Springtime Yellow). On several occasions I've heard him say
how the complexity of modern vehicles makes it almost impossible for amateur mechanics to
work on them. My brother has worked in the automotive field for about 6 years and he shares
this sentiment. His hobby is to turn old Toyota trucks into monster rock crawlers, and one
of the main reasons he prefers older model-years is because they're just easier to work on.
My step-father always preferred 2-stroke dirtbikes for the same reason.

Peewee tries to be, for developers, what a 1960's mustang is for my father-in-law: aesthetically
pleasing, a pleasure to use, and most importantly, something you can easily hack on.
If you need to look under-the-hood (sorry, horrible pun) at the source code, there is only a
single file to read. I've also worked very hard to create useful documentation for peewee, and
at the time I'm writing this, the PDF version of the docs is over 120 pages long!

The simplicity of peewee has proved itself useful time after time as I've added new features
and debugged problems. Even as the code-base has doubled in size since the 2.0 release two
years ago (which was a complete rewrite), the APIs have, if anything, become more simple.
The call stack is never more than a few calls deep, and the objects interact in predictable
ways. radon, a tool that measures the
cyclomatic complexity of Python code, gave peewee an "A", with an average complexity of 2.43.
Here is the list of functions whose complexity is C or worse (where "C" means moderate - slightly complex block):

For comparison, here are the results for SQLAlchemy. Because SQLAlchemy's code-base is much
larger, I've only listed the objects whose complexity is E or worse (where "E" means high - complex block, alarming):

I then used radon once more to measure the lines of source code in each project. Peewee
and the playhouse extension modules weighed in at just over 6,000 SLOC, while SQLAlchemy
was over 85,000. I'm sure that those 85K lines are well written and all serve a purpose,
but 85K is a much more intimidating number for someone interested in learning a library inside
and out.

Have fun out there

More than anything, I want peewee to be fun to use. Because it's so easy to get up and running with peewee, I've found that I'm much more eager to write little scripts or micro-services to solve day-to-day problems. I've written
a note-taking app
that I couldn't function without, a personalized news feed,
a lastpass-style password manager, and many more
fun little apps. Peewee also is great
for doing data analysis -- I've thrown server logs into peewee, used peewee to explore CSV files,
and other projects. In short, I really enjoy using peewee and hope you will, too.

Competition encourages innovation

Even if you never use peewee, it's my hope that the Python community overall benefits from
diversity in the selection of ORM libraries. A little competition forces everyone to step
their game up, and I also think it's good to force the end-users to think critically about
the choice they make in third-party libraries. Pony ORM is another ORM
to come out recently. Pony uses bytecode decompilation to turn Python generator expressions into SQL, an approach that I think is as brilliant as it is crazy! If you're interested in checking
out a comparison of some various Python ORMs, this project
contains the same "Hello world" Flask app written using some of the most popular database libraries.

Links

Thanks for taking the time to read this post, please feel free to leave a comment or contact me.

Example queries with peewee and the Quickstart guide.

Architecture of SQLAlchemy.

D. Richard Hipp's PGCon Keynote and slides.

When to use SQLite.

GitHub repo of same Flask app implemented using a variety of ORMs.

Most importantly, happy hacking!

Show more