The easiest way to understand what Cookiecutter does is to create a simple one and see how it works.
Cookiecutter takes a source directory tree and copies it into your new
project. It replaces all the names that it finds surrounded by templating
tags {{
and }}
with names that it finds in the file
cookiecutter.json
. That's basically it. [1]
The replaced names can be file names, directory names, and strings inside files.
With Cookiecutter, you can easily bootstrap a new project from a standard form, which means you skip all the usual mistakes when starting a new project.
Before you can do anything in this example, you must have Python installed on
your machine. Go to the Python Website and follow
the instructions there. This includes the pip
installer tool. Now run:
$ pip install cookiecutter
To get started, create a directory somewhere on your computer. The name of
this directory will be the name of your Cookiecutter template, but it doesn't
constrain anything else---the generated project doesn't need to use the
template name, for example. Our project will be called HelloCookieCutter1
:
$ mkdir HelloCookieCutter1
$ cd HelloCookieCutter1
Inside this directory, we create the directory tree to be copied into the
generated project. We want to generate a name for this directory, so we put
the directory name in templating tags {{
and }}
(yes, you type the
double-curly-braces onto the command line, just as you see them here):
$ mkdir {{cookiecutter.directory_name}}
$ cd {{cookiecutter.directory_name}}
Anything inside templating tags can be placed inside a namespace. Here, by
putting directory_name
inside the cookiecutter
namespace,
cookiecutter.directory_name
will be looked up from the cookiecutter.json
file as the project is generated by Cookiecutter.
Now we are inside the directory tree that will be copied. For the simplest
possible Cookiecutter template, we'll just include a single file. Again, we
want the file name to be looked up from cookiecutter.json
, so we name it
appropriately:
$ touch {{cookiecutter.file_name}}.py
(touch
creates an empty file; you can just open it up in your editor). Now
edit the file so it contains:
print("Hello, {{cookiecutter.greeting_recipient}}!")
To finish, we create the cookiecutter.json
file itself, so that
Cookiecutter can look up all our templated items. This file goes in our
HelloCookieCutter1
directory, and contains all the names we've used:
{
"directory_name": "Hello",
"file_name": "Howdy",
"greeting_recipient": "Julie"
}
Now we can actually run Cookiecutter and create a new project from our
template. Move to a directory where you want to create the new project. Then
run Cookiecutter and hand it the directory where the template lives. On my
(Windows, so the slashes go back instead of forward) machine, this happens to
be under the Git
directory:
$ cookiecutter C:\Users\bruce\Documents\Git\HelloCookieCutter1
directory_name [Hello]:
file_name [Howdy]:
greeting_recipient [Julie]:
Cookiecutter tells us what the default name for each item is, and gives us the
option of replacing that name with something new. In this case, I just pressed
Return
for each one, to accept all the defaults.
Now we have a generated directory called Hello
, containing a file
Howdy.py
. When we run it:
$ cd Hello
$ python Howdy.py
Hello, Julie!
Voila! Instant generated project!
Note: The project we've created here happens to be Python, but
Cookiecutter is just replacing templated items with names it looks up in
cookiecutter.json
, so you can produce projects of any kind, including
projects that aren't programs.
This is nice, but what if you want to share your Cookiecutter template with
everyone on the Internet? The easiest way is to upload it to a version control
repository. As you might have guessed by the Git
subdirectory, this
example is on GitHub. Conveniently, Cookiecutter can build a project directly
from an internet repository, like the one for this very example. For variety,
this time we'll replace the values from cookiecutter.json
with our own:
$ cookiecutter https://github.com/BruceEckel/HelloCookieCutter1
Cloning into 'HelloCookieCutter1'...
remote: Counting objects: 37, done.
Unpacking objects: 21% (8/37)
remote: Total 37 (delta 19), reused 21 (delta 3), pack-reused 0
Unpacking objects: 100% (37/37), done.
Checking connectivity... done.
directory_name [Hello]: Fabulous
file_name [Howdy]: Zing
greeting_recipient [Julie]: Roscoe
$ cd Fabulous
$ python Zing.py
Hello, Roscoe!
Same effect, but this time produced from the Internet! You'll notice that even
though it says Cloning into 'HelloCookieCutter1'...
, you don't see any
directory called HelloCookieCutter1
in your local directory. Cookiecutter
has its own storage area for cookiecutters, which is in your home directory
in a subdirectory called .cookiecutters
(the leading .
hides the directory
on most operating systems). You don't need to do anything with this directory
but it can sometimes be useful to know where it is.
Now if you ever find yourself duplicating effort when starting new projects, you'll know how to eliminate that duplication using cookiecutter. But even better, lots of people have created and published cookiecutters, so when you are starting a new project, make sure you look at the list of pre-defined cookiecutters first!
[1] | You can also run hooks before and/or after generation, but that's more complex than what we want to cover here. |