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.
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 pipefailstops 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/pythondirectly 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 pipguarantees that packages go into that same interpreter.- The heredoc for
main.pyuses 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.
- commitpedia-admin +3,913 chars