Cookiecutter
Cookiecutter is a command-line utility that creates projects from project templates. It streamlines the setup of new projects, such as Python packages, web applications, or data science projects, by prompting the user for configuration details and rendering files based on Jinja2 templates. Currently at version 2.7.1, it maintains an active release cadence with frequent updates and community contributions, supporting Python 3.10 and newer.
Common errors
-
bash: cookiecutter: command not found
cause The `cookiecutter` executable is not found in your system's PATH. This usually means `cookiecutter` was not installed correctly or its installation directory is not included in the PATH environment variable.fixEnsure `cookiecutter` is installed via `pip install cookiecutter`. If it is, find the Python `Scripts` directory (e.g., `~/.local/bin` on Linux/macOS, or `Python\Scripts` on Windows) where `cookiecutter` is located and add it to your system's PATH environment variable. Alternatively, run it as a Python module: `python -m cookiecutter <template_url>`. -
jinja2.exceptions.TemplateNotFound: <template_name>
cause This error occurs when Jinja2, the templating engine used by Cookiecutter, cannot locate a template file that is being referenced within your Cookiecutter template. This can happen if the path to the template is incorrect, or if files within your Cookiecutter template contain Jinja2 syntax that Cookiecutter attempts to render as a template itself.fixCheck the paths to templates within your `cookiecutter` template for typos. If the error is for a file that *shouldn't* be rendered as a Jinja2 template, use `_copy_without_render` in `cookiecutter.json` to exclude it, or properly escape Jinja2 syntax within that file using `{{ "{{" }}` and `{{ "}}" }}` to prevent premature rendering. -
cookiecutter.exceptions.RepositoryNotFound: A valid repository for "<template_path>" could not be found in the following locations:
cause Cookiecutter cannot find the specified template repository. This could be due to an incorrect URL, a typo in the path, the repository not existing, or a local path not pointing to a valid Cookiecutter template (i.e., missing `cookiecutter.json` at its root).fixVerify the template URL or local path for correctness. Ensure the `cookiecutter.json` file is present in the root of your template directory if you are using a local template. For remote repositories, check your internet connection and the repository's accessibility. -
cookiecutter.exceptions.UndefinedVariableInTemplate: 'foo' is undefined
cause A Jinja2 template within your Cookiecutter template is attempting to use a variable (e.g., 'foo') that has not been defined in the `cookiecutter.json` file or provided as `extra_context` when running `cookiecutter`.fixDefine the missing variable in your `cookiecutter.json` file, ensuring it has a default value. Alternatively, provide the variable's value using the `--extra-context` command-line argument or `extra_context` parameter if calling `cookiecutter` programmatically.
Warnings
- breaking Python 3.9 and older versions are no longer officially supported. `cookiecutter` now requires Python 3.10 or newer for versions 2.7.0 and later.
- gotcha In version 2.7.0, the `cookiecutter -V` command incorrectly reported the version as 2.6.0, despite the installed package being 2.7.0. The programmatic `cookiecutter.__version__` was correct.
- gotcha Cookiecutter templates can execute arbitrary code through hook scripts (e.g., `pre_gen_project.py`). Users should only use templates from trusted sources, as malicious templates can compromise your system.
- gotcha When using `jinja2_time` in templates, ensure a timezone is explicitly set (e.g., in `cookiecutter.json` or environment variables) to avoid unexpected date/time behavior, as `jinja2_time` does not provide a default timezone.
Install
-
pip install cookiecutter
Imports
- cookiecutter
from cookiecutter.main import cookiecutter
Quickstart
from cookiecutter.main import cookiecutter
import os
import shutil
# Define a temporary output directory
output_dir = './my_new_project_temp'
# Define a simple local template for demonstration
template_path = './my_template'
# Create a simple template for demonstration purposes
# In a real scenario, you'd clone from a Git URL or use a local template.
if not os.path.exists(template_path):
os.makedirs(os.path.join(template_path, '{{ cookiecutter.repo_name }}'))
with open(os.path.join(template_path, 'cookiecutter.json'), 'w') as f:
f.write('{"repo_name": "my-project"}')
with open(os.path.join(template_path, '{{ cookiecutter.repo_name }}', 'README.md'), 'w') as f:
f.write('Hello, {{ cookiecutter.repo_name }}!')
print(f"Generating project from template: {template_path}")
# Run cookiecutter programmatically
# This will prompt for 'repo_name' unless `no_input=True` is used
# or default_context is provided.
# For a runnable quickstart, we'll provide default_context and no_input.
try:
cookiecutter(
template_path,
no_input=True, # Set to False to be prompted
extra_context={'repo_name': 'my-generated-project'},
output_dir=output_dir,
overwrite_if_exists=True
)
print(f"Project successfully generated in {os.path.join(output_dir, 'my-generated-project')}")
# Verify a file exists
generated_file = os.path.join(output_dir, 'my-generated-project', 'README.md')
if os.path.exists(generated_file):
with open(generated_file, 'r') as f:
print(f"Content of {generated_file}:\n{f.read()}")
else:
print("Error: Generated file not found.")
except Exception as e:
print(f"An error occurred: {e}")
finally:
# Clean up the temporary template and generated project
if os.path.exists(template_path):
shutil.rmtree(template_path)
if os.path.exists(output_dir):
shutil.rmtree(output_dir)
print("Cleanup complete.")