Skip to content
Commitpedia
Log in Join & edit

Bootstrap a new Python project with a venv

A Bash script that creates a project folder with a virtual environment, .gitignore, requirements.txt and a starter main.py, then runs it to prove everything works.

Edit history of Bootstrap a new Python project with a venv: 1 recorded edit
Edit history · 1 edit
Type
Script
Edits
1
Editors
1
First issued
15 Oct 2026
Last edit
15 Oct 2026
Language
bash
Licence
CC0-1.0

Every new Python project starts with the same few steps: make a folder, create a virtual environment, ignore it in Git, and add a first file. This script does all of it in one command and refuses to overwrite an existing environment. It needs nothing beyond Bash and a Python 3 interpreter.

Usage

chmod +x new-python-project.sh
./new-python-project.sh my-tool                # uses python3
./new-python-project.sh my-tool python3.12     # pick a specific Python version

Output for a fresh folder:

Created .venv with Python 3.12.x
Created .gitignore
Created main.py
Created empty requirements.txt
Hello from your new project!

Done. Next steps:
  cd my-tool
  source .venv/bin/activate
  python -m pip install <package> && python -m pip freeze > requirements.txt

If the folder already contains a requirements.txt (for example a project you just cloned), the script installs those packages into the new environment instead of creating an empty file. Existing .gitignore and main.py files are left untouched.

The script

#!/usr/bin/env bash
# Create a Python project folder with a virtual environment, .gitignore and a starter script.
set -euo pipefail

usage() {
  echo "usage: $0 PROJECT_DIR [PYTHON]" >&2
  echo "  PYTHON defaults to python3, e.g. python3.12" >&2
  exit 1
}

[[ $# -ge 1 && $# -le 2 ]] || usage
project_dir=$1
python=${2:-python3}

command -v "$python" >/dev/null 2>&1 || { echo "error: $python not found" >&2; exit 1; }

if [[ -e "$project_dir/.venv" ]]; then
  echo "error: $project_dir/.venv already exists" >&2
  exit 1
fi

mkdir -p "$project_dir"
cd "$project_dir"

"$python" -m venv .venv
echo "Created .venv with $(.venv/bin/python --version)"

if [[ ! -f .gitignore ]]; then
  printf '%s\n' '.venv/' '__pycache__/' '*.pyc' '.pytest_cache/' > .gitignore
  echo "Created .gitignore"
fi

if [[ ! -f main.py ]]; then
  cat > main.py <<'PY'
def main():
    print("Hello from your new project!")


if __name__ == "__main__":
    main()
PY
  echo "Created main.py"
fi

if [[ -f requirements.txt ]]; then
  .venv/bin/python -m pip install -r requirements.txt
else
  touch requirements.txt
  echo "Created empty requirements.txt"
fi

.venv/bin/python main.py

cat <<MSG

Done. Next steps:
  cd $project_dir
  source .venv/bin/activate
  python -m pip install <package> && python -m pip freeze > requirements.txt
MSG

How it works

  • set -euo pipefail stops the script on the first failed command, on use of an unset variable, and on failures inside pipelines, so it never continues in a half-broken state.
  • command -v "$python" checks that the requested interpreter exists before doing any work.
  • The script calls .venv/bin/python directly instead of activating the environment. Activation only changes the current shell, and a script runs in its own shell, so calling the interpreter by path is the reliable way.
  • python -m pip guarantees that packages go into that same interpreter.
  • The heredoc for main.py uses a quoted delimiter (<<'PY'), which stops Bash from expanding anything inside the Python code.

Windows

On Windows the environment layout differs (.venv\Scripts\python.exe instead of .venv/bin/python). Run the script under WSL, or do the same steps by hand in PowerShell: py -m venv .venv, then .venv\Scripts\Activate.ps1.

Ideas to extend it

Run git init when no repository exists, add a tests/ folder with a first pytest file, or write a minimal pyproject.toml. If you prefer uv, the core of the script becomes uv init "$project_dir", which creates a project with pyproject.toml and sets up the environment on first uv run.

See also

  • 0001 Virtual environments with venv A virtual environment is a private folder of Python packages for one project, so projects never fight over versions. Create one with… Beginner · Concept · Any system Article Environments & packages 15 Oct 2026
  • 0007 Fix: ModuleNotFoundError: No module named ‘…’ Python cannot find a module you import. Usually the package was installed into a different interpreter or virtual environment than the one… Beginner · Fix · Any system Article Common errors · Environments & packages 15 Oct 2026
  • 0261 Build a Python command-line to-do app: from empty folder to installable command Create a small to-do tool in Python with argparse and JSON storage, test it with pytest and package it with pyproject.toml so… Beginner · Tutorial · Any system Article Environments & packages · Files & automation · Testing 15 Oct 2026

Repos in the wild

  • uv: Python package and project manager astral-sh/uv uv is a very fast Python package and project manager written in Rust. It replaces pip, venv and related tools, manages lock files and can install Python itself. GitHub

History

Every saved edit is kept. The plot on the sleeve draws one line per edit. Open any edit to see exactly what changed.

  1. commitpedia-admin +3,913 chars

Report a problem

Something wrong, unsafe or copied? Tell the editors.
What is wrong?