Programming with Python › Python Setup and First Programs › Day 43
Hands-on lab — Day 43: Installing Python and Virtual Environments
- ← Back to the Day 43 lesson
- Open the hands-on files on GitHub — clone or download them from the public labs repository
- Local path in your clone:
labs/sections/programming-with-python/day-043-installing-python-and-virtual-environments/
Commands
Setup
cd labs/sections/programming-with-python/day-043-installing-python-and-virtual-environments Run
bash examples/venv_demo.sh
bash starter/venv_demo.sh Test
bash tests/run_tests.sh File tree
examples/venv_demo.sh expected-output/FIELDS.md expected-output/sample-macos.txt metadata.yml README.md requirements/README.md security.md starter/venv_demo.sh starter/venv-worksheet.md tests/run_tests.sh troubleshooting.md
Lab README
Day 043 lab — Create and Verify a Virtual Environment
Lesson
- Lesson title: Installing Python and Virtual Environments
- Day number: 43 of 365
- Lesson article: https://ai-roadmap-365.github.io/day-043-installing-python-and-virtual-environments
- Lab files: everything you need is in this directory — follow “How to run” below.
- Browse the course locally: from the repository root, this lab also appears in the course website at
/labs/day-043-installing-python-and-virtual-environmentswhen the site is running.
Purpose
Day 43's lesson explains why every project should keep its packages isolated in
a virtual environment. This lab makes that concrete and offline: you create
a venv with python3 -m venv, activate it, and watch which python and
sys.prefix move inside the environment — proof, on your own machine, that
the isolation is real. No packages are downloaded and no network is used.
Learning objectives
- Create a virtual environment with
python3 -m venv .venv. - Activate and deactivate it, and explain what activation changes.
- Prove isolation by inspecting
which pythonandsys.prefixbefore and after activation. - Record a project's dependencies in a
requirements.txtfile. - Run an automated test script and interpret its pass/fail output.
Prerequisites
- The Day 43 lesson (read it first — it explains every concept this lab demonstrates).
- Course 1 fluency: the terminal,
PATH(Day 11), and package managers (Day 13). - Python 3 installed (
python3 --versionprints 3.x). Seerequirements/README.mdif it is missing.
Supported operating systems
- macOS — fully supported (tested on macOS with Apple Silicon, Python 3.14.0).
- Linux — fully supported (any distribution with
python3and thevenvmodule; installpython3-venvon minimal Debian/Ubuntu). - Windows — use
.venv\Scripts\activatein PowerShell, or run the scripts unchanged inside WSL (recommended). Seetroubleshooting.md.
Hardware requirements
Any computer made in roughly the last 15 years. The lab creates a tiny, empty environment in a temp directory; it needs no meaningful RAM, disk, or GPU.
Required software
python3≥ 3.8 with thevenvmodule (bundled since Python 3.3).bash≥ 3.2 (preinstalled on macOS and Linux).
No PyPI packages, accounts, API keys, or network access are required.
Free and open-source options
Everything in this lab is free and open source: Python, the venv module, and
pip all ship with Python at no cost, and PyPI (used in later labs, not this
one) is a free public repository. No purchase or account is ever needed.
Installation
None beyond Python itself. Copy this directory (or clone the repository) and change into it:
cd labs/sections/programming-with-python/day-043-installing-python-and-virtual-environments
File structure
day-043-installing-python-and-virtual-environments/
├── README.md ← you are here
├── metadata.yml ← machine-readable lab metadata
├── starter/
│ ├── venv_demo.sh ← YOUR working file (4 exercises)
│ └── venv-worksheet.md ← worksheet for the practice assignment
├── examples/
│ └── venv_demo.sh ← completed reference implementation
├── tests/
│ └── run_tests.sh ← automated, offline checks
├── expected-output/
│ ├── sample-macos.txt ← real captured run (macOS, Apple Silicon)
│ └── FIELDS.md ← required behaviour on every platform
├── requirements/
│ └── README.md ← dependency statement (just Python 3)
├── troubleshooting.md
└── security.md
How to run
From this directory:
## 1. See the finished result first
bash examples/venv_demo.sh
## 2. Your task: complete the four exercises in the starter, then run it
bash starter/venv_demo.sh
## 3. Check your work
bash tests/run_tests.sh
What the commands do
bash examples/venv_demo.sh— the reference script. It makes a temp directory, prints the interpreter version, creates.venvwithpython3 -m venv .venv, showswhich pythonbefore activation, activates the venv, then showswhich python,which pip, andsys.prefixall pointing inside.venv, writes arequirements.txt, deactivates, and deletes the temp directory on exit.bash starter/venv_demo.sh— the same scaffolding with four numbered exercises for you to fill in: (1) create the venv, (2) activate it, (3) prove isolation by printingwhich pythonandsys.prefix, (4) deactivate. Each exercise comment names the exact command.bash tests/run_tests.sh— offline checks:python3is available, a venv can be created,sys.prefixpoints inside it, activation redirectswhich python, cleanup leaves nothing behind, the example runs and confirms isolation, and the starter still ships its four exercises.
Expected output
See expected-output/sample-macos.txt — a
real captured run. The key lines:
--- Step 4: activate and prove isolation ---
which python -> /private/var/folders/.../venv-demo.qPEavX/.venv/bin/python
sys.prefix -> /private/var/folders/.../venv-demo.qPEavX/.venv
OK: sys.prefix is inside the .venv — the environment is isolated.
Your temp path will differ on every run — only the shape matters.
expected-output/FIELDS.md lists the required
behaviour and documents platform differences.
Validation steps
- Run
bash examples/venv_demo.sh— it must exit without errors and printOK: sys.prefix is inside the .venv. - Complete
starter/venv_demo.sh(replace all fourEXERCISE_*_NOT_DONElines) and run it; confirm activation changeswhich python. - Fill in
starter/venv-worksheet.mdwith your real before/after paths. - Run the tests (next section) — all checks must pass.
Tests
bash tests/run_tests.sh
Expected final line: 11 checks, 0 failure(s). The command exits 0 on success
and non-zero on any failure, so it can run in CI. It needs no network.
Cleanup
Nothing to clean up: both scripts do all their work in a temporary directory
and remove it on exit (via a cleanup trap), even if a step fails. To reset your
edited starter, restore it from git: git checkout -- starter/venv_demo.sh.
Troubleshooting
See troubleshooting.md for the full list (python vs
python3, activation per shell and on Windows, missing python3-venv, keeping
.venv out of git).
Security notes
See security.md. Short version: the scripts run no network calls,
need no elevated privileges, work only in a temp directory, and never commit
anything. Never commit a .venv folder; pin your dependencies.
Extension exercises
- With a venv active, run
pip listandpip freeze— note that a fresh venv has almost nothing installed, which is the point of starting clean. - Create two venvs in two folders and confirm, with
sys.prefix, that each is independent of the other. - Add a real
.gitignorecontaining.venv/to a scratch project and verify withgit statusthat the environment is ignored whilerequirements.txtis tracked.
Navigation
- Previous day: Day 42 — Section Review: Your Computing Foundations Toolkit
(
labs/sections/computing-foundations/day-042-section-review-your-computing-foundations-toolkit/). - Next day: Day 44 — Variables and Types
(
labs/sections/programming-with-python/day-044-variables-and-types/, to be written).
Expected output
FIELDS.md
# Required behaviour (all platforms)
A correct run of `examples/venv_demo.sh` must, on any supported system:
1. Print the interpreter version (`Python 3.x.y`).
2. Create a `.venv` directory containing an `activate` script and its own
`python` (in `.venv/bin/` on macOS and Linux, `.venv\Scripts\` on Windows).
3. Show `which python` pointing at the **global** interpreter before
activation and at `.../.venv/bin/python` after activation.
4. Report `sys.prefix` as a path that ends in `.venv` — the proof of
isolation — and print the `OK: ... the environment is isolated.` line.
5. Write a `requirements.txt` documenting the Python version and the
standard-library-only note.
6. Deactivate and remove the temporary directory, leaving nothing behind.
`sample-macos.txt` in this directory is a real captured run (macOS, Apple
Silicon, Python 3.14.0, 2026-07-12).
## Platform differences (documented, not fabricated)
- **Temp path.** The working directory is created by `mktemp` and is random;
every run prints a different path. macOS resolves `/var` to `/private/var`,
so paths appear under `/private/var/folders/...`; Linux typically uses
`/tmp/venv-demo.XXXXXX`.
- **Global interpreter path.** Before activation, `which python` reflects
wherever your Python came from — e.g. `/opt/homebrew/...` (Homebrew on Apple
Silicon), `/usr/bin/python3` (system), or a `pyenv` shim. Only the *change*
on activation matters, not the exact path.
- **`.venv/bin` contents.** Newer Python versions add extra convenience
symlinks (for example Python 3.14 adds a `𝜋thon` alias). The essential
entries are `activate`, `python`, `pip`.
- **Windows.** Activation is `.venv\Scripts\activate` and the interpreter is
`.venv\Scripts\python.exe`. Run the equivalent commands in PowerShell, or run
the scripts unchanged inside WSL, where the Linux paths apply.
sample-macos.txt
Real captured run of `bash examples/venv_demo.sh` on macOS (Apple Silicon,
Python 3.14.0, 2026-07-12). The temp path is randomly generated, so yours will
differ — only the shape matters.
=== Virtual Environment Demo ===
Working directory: /private/var/folders/7j/xxxx/T/venv-demo.qPEavX
--- Step 1: the interpreter ---
Python 3.14.0
--- Step 2: create the virtual environment (offline) ---
Created .venv/ — contents of .venv/bin (or Scripts on Windows):
activate
pip
pip3
python
python3
--- Step 3: which python BEFORE activation ---
which python -> /opt/homebrew/opt/python@3.14/libexec/bin/python
--- Step 4: activate and prove isolation ---
which python -> /private/var/folders/7j/xxxx/T/venv-demo.qPEavX/.venv/bin/python
which pip -> /private/var/folders/7j/xxxx/T/venv-demo.qPEavX/.venv/bin/pip
sys.prefix -> /private/var/folders/7j/xxxx/T/venv-demo.qPEavX/.venv
OK: sys.prefix is inside the .venv — the environment is isolated.
--- Step 5: record dependencies in requirements.txt ---
requirements.txt:
# Built and verified with Python 3.14.0
# This project uses only the Python standard library — no PyPI packages required.
--- Step 6: deactivate ---
which python -> /opt/homebrew/opt/python@3.14/libexec/bin/python (back to global)
=== Demo complete — temp directory will be removed on exit ===
Test run (`bash tests/run_tests.sh`), same machine:
Testing venv creation and isolation (offline) ...
ok: python3 is available
ok: python3 -m venv creates an environment
ok: environment has bin/activate
ok: environment has its own python
ok: sys.prefix points inside the venv
ok: activation redirects 'which python' into the venv
ok: cleanup leaves nothing behind
ok: examples/venv_demo.sh exits successfully
ok: example confirms isolation
ok: example cleans up its temp directory
ok: starter ships all four exercises
11 checks, 0 failure(s).
Source files
examples/venv_demo.sh (2683 bytes)
#!/usr/bin/env bash
# Day 043 lab — completed reference implementation.
# Creates a virtual environment in a temporary directory, proves that
# activation isolates python/pip, writes a requirements.txt, then
# deactivates and cleans everything up. Fully OFFLINE: no network needed.
#
# Run from the lab directory:
# bash examples/venv_demo.sh
set -euo pipefail
# Work in a throwaway temp directory so nothing is left in your project.
# Resolve symlinks (on macOS /var is a link to /private/var) so later path
# comparisons against sys.prefix line up exactly.
work_dir="$(mktemp -d "${TMPDIR:-/tmp}/venv-demo.XXXXXX")"
work_dir="$(cd "${work_dir}" && pwd -P)"
# Always clean up, even if a command fails partway through.
cleanup() {
# Leaving an active venv is harmless in a subshell, but deactivate if we can.
type deactivate >/dev/null 2>&1 && deactivate || true
rm -rf "${work_dir}"
}
trap cleanup EXIT
echo "=== Virtual Environment Demo ==="
echo "Working directory: ${work_dir}"
cd "${work_dir}"
echo
echo "--- Step 1: the interpreter ---"
python3 --version
echo
echo "--- Step 2: create the virtual environment (offline) ---"
python3 -m venv .venv
echo "Created .venv/ — contents of .venv/bin (or Scripts on Windows):"
ls .venv/bin >/dev/null 2>&1 && ls .venv/bin | sed 's/^/ /' || true
echo
echo "--- Step 3: which python BEFORE activation ---"
before="$(command -v python || echo '(no python on PATH)')"
echo "which python -> ${before}"
echo
echo "--- Step 4: activate and prove isolation ---"
# shellcheck disable=SC1091
source .venv/bin/activate
after="$(command -v python)"
echo "which python -> ${after}"
echo "which pip -> $(command -v pip)"
prefix="$(python -c 'import sys; print(sys.prefix)')"
echo "sys.prefix -> ${prefix}"
# Confirm sys.prefix really points inside our .venv folder.
case "${prefix}" in
"${work_dir}"/.venv*) echo "OK: sys.prefix is inside the .venv — the environment is isolated." ;;
*) echo "WARNING: sys.prefix is not inside .venv" ; exit 1 ;;
esac
echo
echo "--- Step 5: record dependencies in requirements.txt ---"
# A fresh venv installs no third-party packages; document that we rely on the
# standard library only, and pin the Python version used to build it.
{
echo "# Built and verified with $(python --version)"
echo "# This project uses only the Python standard library — no PyPI packages required."
} > requirements.txt
echo "requirements.txt:"
sed 's/^/ /' requirements.txt
echo
echo "--- Step 6: deactivate ---"
deactivate
echo "which python -> $(command -v python || echo '(no python on PATH)') (back to global)"
echo
echo "=== Demo complete — temp directory will be removed on exit ==="
metadata.yml (615 bytes)
lesson_id: D043
day: 43
kind: configuration-activity
languages: [bash, python]
setup_commands:
- cd labs/sections/programming-with-python/day-043-installing-python-and-virtual-environments
run_commands:
- bash examples/venv_demo.sh
- bash starter/venv_demo.sh
test_commands:
- bash tests/run_tests.sh
cleanup_commands:
- '# nothing to clean: the scripts use a temp directory and remove it themselves'
requires_network: false
requires_api_key: false
estimated_minutes: 30
last_executed: '2026-07-12'
executed_on: 'macOS (Apple Silicon), Python 3.14.0, bash tests/run_tests.sh → 11 checks, 0 failure(s).'
requirements/README.md (1417 bytes)
# Dependencies — Day 043 lab
**Just Python 3 and a POSIX shell.** There are no PyPI packages to install and
no network access is required at any step — creating a virtual environment uses
only tools that ship with Python.
- `python3` **≥ 3.8** (any modern 3.x is fine; the `venv` module has shipped
with Python since 3.3). Preinstalled on macOS and most Linux distributions.
- `bash` ≥ 3.2 (preinstalled on macOS and Linux).
## Checking what you have
```bash
python3 --version
```
If that prints `Python 3.x.y`, you are ready.
## If Python 3 is missing
Install it once, using the package-manager skills from Day 13:
- **macOS:** `brew install python` (Homebrew), or download the installer from
the official python.org downloads page.
- **Debian/Ubuntu Linux:** `sudo apt update && sudo apt install python3 python3-venv`
- **Fedora Linux:** `sudo dnf install python3`
- **Windows:** install from the official python.org downloads page (tick "Add
Python to PATH"), or use WSL and follow the Linux instructions.
On some minimal Debian/Ubuntu systems the `venv` module is packaged
separately — that is why `python3-venv` is listed above. If
`python3 -m venv .venv` complains that `venv` is unavailable, install that
package.
This lab installs nothing else. Later labs will declare their Python packages
in a `requirements.txt`, which is exactly the reproducibility habit this lesson
introduces.
starter/venv_demo.sh (1892 bytes)
#!/usr/bin/env bash
# Day 043 lab — YOUR working file.
#
# The scaffolding (temp directory, cleanup, the interpreter check) is done for
# you. Your job is the four numbered exercises below: replace each placeholder
# line with the single command named in its comment. The completed reference is
# examples/venv_demo.sh — try to do it yourself first, then compare.
#
# Everything here is OFFLINE: no network is needed at any step.
#
# Run from the lab directory:
# bash starter/venv_demo.sh
set -euo pipefail
# --- Scaffolding (already done for you) ---
work_dir="$(mktemp -d "${TMPDIR:-/tmp}/venv-demo.XXXXXX")"
cleanup() {
type deactivate >/dev/null 2>&1 && deactivate || true
rm -rf "${work_dir}"
}
trap cleanup EXIT
echo "=== Virtual Environment Demo (starter) ==="
echo "Working directory: ${work_dir}"
cd "${work_dir}"
echo
echo "--- The interpreter (already done) ---"
python3 --version
echo
echo "--- Exercise 1: create a virtual environment named .venv ---"
# Replace the next line with: python3 -m venv .venv
echo "EXERCISE_1_NOT_DONE: create the .venv here"
echo
echo "--- Exercise 2: activate the environment ---"
# Replace the next line with: source .venv/bin/activate
echo "EXERCISE_2_NOT_DONE: activate the .venv here"
echo
echo "--- Exercise 3: prove isolation ---"
# After activating, these two commands prove the environment is active.
# Replace the next line with BOTH commands (one per line):
# command -v python
# python -c 'import sys; print("sys.prefix:", sys.prefix)'
echo "EXERCISE_3_NOT_DONE: print 'which python' and sys.prefix here"
echo
echo "--- Exercise 4: deactivate the environment ---"
# Replace the next line with: deactivate
echo "EXERCISE_4_NOT_DONE: deactivate the .venv here"
echo
echo "=== Done — temp directory will be removed on exit ==="
echo "When all four EXERCISE_*_NOT_DONE lines are replaced, run tests/run_tests.sh."
starter/venv-worksheet.md (1785 bytes)
# Virtual environment worksheet — Day 043
Fill this in for **your** machine as you work through the exercises. The goal is
to see, with your own eyes, that activating a virtual environment changes which
Python you are using.
## 1. Your Python
Run `python3 --version` and record the output:
- My Python version: `____________________`
## 2. `which python` before activation
Before activating any environment, run `which python` (or `command -v python`)
and record the full path:
- Before activation, `which python` prints: `____________________`
## 3. Create and activate
Run these from a scratch folder:
```bash
mkdir venv-demo && cd venv-demo
python3 -m venv .venv
source .venv/bin/activate
```
- Did your prompt gain a `(.venv)` marker? (yes / no): `______`
## 4. `which python` after activation
With the environment active, run `which python` again:
- After activation, `which python` prints: `____________________`
- Is this path different from step 2? (yes / no): `______`
## 5. Prove isolation with `sys.prefix`
Run:
```bash
python -c "import sys; print(sys.prefix)"
```
- `sys.prefix` prints: `____________________`
- Does this path end in `.venv`? (yes / no): `______`
## 6. Explain it (4–6 sentences)
In your own words, what did activation change, and why does `sys.prefix`
pointing inside `.venv` prove your project's packages are isolated from the
global Python?
```
____________________________________________________________________
____________________________________________________________________
____________________________________________________________________
```
## 7. Clean up
```bash
deactivate
cd .. && rm -rf venv-demo
```
- After `deactivate`, `which python` prints: `____________________`
(it should match step 2 again).
tests/run_tests.sh (3690 bytes)
#!/usr/bin/env bash
# Tests for the Day 043 lab. Run from the lab directory:
# bash tests/run_tests.sh
#
# Verifies, entirely OFFLINE, that a virtual environment can be created, that
# activation isolates the interpreter (sys.prefix points inside the venv), and
# that cleanup leaves nothing behind. Also checks that the completed example
# script runs and that the starter still ships its four exercises.
set -u
lab_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
failures=0
checks=0
check() {
local label="$1" ok="$2"
checks=$((checks + 1))
if [ "${ok}" = "yes" ]; then
echo " ok: ${label}"
else
echo " FAIL: ${label}"
failures=$((failures + 1))
fi
}
echo "Testing venv creation and isolation (offline) ..."
# Python 3 must be available.
if command -v python3 >/dev/null 2>&1; then
check "python3 is available" "yes"
else
check "python3 is available" "no"
echo
echo "${checks} checks, ${failures} failure(s)."
exit 1
fi
# 1. A venv can be created in a throwaway temp directory.
# Resolve symlinks so the path lines up with what sys.prefix reports.
work_dir="$(mktemp -d "${TMPDIR:-/tmp}/venv-test.XXXXXX")"
work_dir="$(cd "${work_dir}" && pwd -P)"
created="no"
if python3 -m venv "${work_dir}/.venv" >/dev/null 2>&1; then created="yes"; fi
check "python3 -m venv creates an environment" "${created}"
# 2. The environment has an activate script and a python interpreter.
[ -f "${work_dir}/.venv/bin/activate" ] && check "environment has bin/activate" "yes" || check "environment has bin/activate" "no"
[ -x "${work_dir}/.venv/bin/python" ] && check "environment has its own python" "yes" || check "environment has its own python" "no"
# 3. After activation, sys.prefix points INSIDE the venv.
prefix=""
# shellcheck disable=SC1090
if source "${work_dir}/.venv/bin/activate" 2>/dev/null; then
prefix="$(python -c 'import sys; print(sys.prefix)' 2>/dev/null)"
which_python="$(command -v python)"
type deactivate >/dev/null 2>&1 && deactivate || true
fi
case "${prefix}" in
"${work_dir}"/.venv*) check "sys.prefix points inside the venv" "yes" ;;
*) check "sys.prefix points inside the venv" "no" ;;
esac
case "${which_python:-}" in
"${work_dir}"/.venv/bin/python) check "activation redirects 'which python' into the venv" "yes" ;;
*) check "activation redirects 'which python' into the venv" "no" ;;
esac
# 4. Cleanup leaves nothing behind.
rm -rf "${work_dir}"
[ ! -e "${work_dir}" ] && check "cleanup leaves nothing behind" "yes" || check "cleanup leaves nothing behind" "no"
# 5. The completed example script runs end to end and confirms isolation.
if out="$(bash "${lab_dir}/examples/venv_demo.sh" 2>&1)"; then
check "examples/venv_demo.sh exits successfully" "yes"
echo "${out}" | grep -q "the environment is isolated" && check "example confirms isolation" "yes" || check "example confirms isolation" "no"
else
check "examples/venv_demo.sh exits successfully" "no"
echo "${out}" | sed 's/^/ /'
fi
# 6. The example leaves no temp directory behind (it cleans up its own).
leftover="$(find "${TMPDIR:-/tmp}" -maxdepth 1 -name 'venv-demo.*' 2>/dev/null | wc -l | tr -d ' ')"
[ "${leftover}" = "0" ] && check "example cleans up its temp directory" "yes" || check "example cleans up its temp directory" "no"
# 7. The starter still ships its four exercises for the learner.
starter="${lab_dir}/starter/venv_demo.sh"
missing=0
for n in 1 2 3 4; do
grep -q "EXERCISE_${n}_NOT_DONE" "${starter}" || missing=1
done
[ "${missing}" = "0" ] && check "starter ships all four exercises" "yes" || check "starter ships all four exercises" "no"
echo
echo "${checks} checks, ${failures} failure(s)."
[ "${failures}" -eq 0 ]
Troubleshooting
Troubleshooting — Day 043 lab
python3: command not found
Python 3 is not installed or not on your PATH. See requirements/README.md
for the one-line install for your system. On Windows, python (not python3)
is often the command; if python --version shows a 3.x version, use python
in place of python3 for the venv-creation step.
python vs python3 confusion
Outside a virtual environment, prefer python3 — on some systems python
still means the old Python 2, or does not exist at all. Inside an active
venv, python is correct and points at the venv's interpreter. When in doubt,
run which python (macOS/Linux) or where python (Windows) to see exactly
which interpreter you are calling.
python3 -m venv fails with "ensurepip is not available"
On some minimal Debian/Ubuntu installs the venv support is a separate
package. Install it: sudo apt install python3-venv. No other lab step needs
elevated privileges.
source .venv/bin/activate — "no such file or directory"
Either you are not in the folder that contains .venv, or the environment did
not build. List it: ls .venv/bin/ should show an activate file. On
Windows the activation path is different:
- PowerShell:
.venv\Scripts\Activate.ps1 - Command Prompt:
.venv\Scripts\activate.bat
If PowerShell blocks the script with an execution-policy error, run it inside WSL instead, where the Linux commands apply unchanged.
Activation "doesn't work" — which python looks the same
Activation only affects the shell you run it in. If you opened a new terminal
tab or ran the script in a subshell, activate again in the shell you are
actually using. Also note: some shells do not show the (.venv) prompt marker
even when the venv is active — trust which python and sys.prefix, not the
prompt text.
Should I commit .venv to git?
No. A virtual environment is large, machine-specific, and fully rebuildable.
Add it to your .gitignore:
.venv/
Commit your requirements.txt instead — that is the portable recipe that lets
anyone rebuild an identical environment.
The tests report a failure
Run bash tests/run_tests.sh and read which line says FAIL. Each check names
exactly what it verified (venv created, sys.prefix inside the venv, cleanup,
the example script). The most common cause is a Python that is too old or a
missing python3-venv package — fix that first, then re-run.
Security notes
Security notes — Day 043 lab
-
What the scripts do: create a Python virtual environment inside a throwaway temporary directory, print which interpreter is active, write a small
requirements.txt, then deactivate and delete the temp directory. They make no network connections, need no elevated privileges, and write nothing outside their own temp folder. -
Temp directory only. All work happens in a directory created by
mktempand removed on exit (even if a step fails, via a cleanup trap). Nothing is written into your project or your home directory, so there is nothing to accidentally commit from this lab. -
Never commit a virtual environment. In your own projects, add
.venv/to.gitignore. A committed venv is large, machine-specific, and can leak local paths; the correct thing to share is therequirements.txtrecipe. -
Pin your dependencies. When you start installing real packages from PyPI, record exact versions (
pip freeze > requirements.txt, which writes lines likerequests==2.32.3). Pinning is a security practice as well as a reproducibility one: it stops an unexpected or tampered newer version from being pulled in silently under a name you already trust. Install only packages you mean to, and watch for typo-squatted names (e.g.reqeustsforrequests). -
Read before you run. Both scripts here are short and commented — read them first. Running unread shell scripts is a common way developers get compromised; every script in this course is small enough to read before executing.