Virtual environments and packages
Important
GitHub Classroom
- Accept the GitHub Classroom assignment for this chapter.
- Complete any email / invitation steps your course requires.
- Clone your repo and open the project in your editor.
By this point in the course you have been writing Python with whatever interpreter your template and editor use. For the final web chapters, you want an isolated environment and the right libraries installed cleanly.
Virtual environments
A virtual environment is a directory of packages for one project.
python3 -m venv .venv # the .venv will be the name of the folder for your environment
Activate:
- macOS / Linux:
source .venv/bin/activate - Windows (cmd):
.venv\Scripts\activate.bat - Windows (PowerShell):
.venv\Scripts\Activate.ps1
Deactivate: deactivate
Tip
After activating, run
python --versionandwhich python(orwhere python) to confirm you are inside the venv.
Installing web and HTTP dependencies
Your Classroom template may ship pyproject.toml or requirements.txt. Typical packages for the closing chapters:
fastapi— web frameworkuvicorn— ASGI serverpydantic— data validation (you already used it earlier; ensure it is installed here if needed)httpx2— HTTP client
Example:
pip install fastapi uvicorn pydantic httpx2
Or use pip install -r requirements.txt, uv sync, or Poetry, per your template.
A tiny API in your venv
After installing packages, prove the venv works by running a minimal FastAPI app. Don’t worry, the full capstone project is just around the corner.
Create hello.py in your project root (any filename is fine; just something to keep it separate from app.py in later chapters):
# hello.py
import argparse
import uvicorn
from fastapi import FastAPI
# the object for the app itself
app = FastAPI()
# specify the root page of the app
@app.get("/")
def root():
return {"message": "it works!"}
# the main function to drive all of it
def main() -> None:
parser = argparse.ArgumentParser(description="Run the demo API")
parser.add_argument("--host", default="127.0.0.1", help="Host to bind")
parser.add_argument("--port", type=int, default=8000, help="Port to listen on")
parser.add_argument(
"--reload",
action="store_true",
help="Restart on file changes (development only)",
)
args = parser.parse_args()
uvicorn.run("hello:app", host=args.host, port=args.port, reload=args.reload)
if __name__ == "__main__":
main()
Two routes, two JSON objects—same pattern you will use for the real web chapters. main() starts Uvicorn when you run the file as a script (see below).
Start the server
With .venv activated, from the directory that contains hello.py, you can start the app in either of two ways.
1. Uvicorn CLI (points at the app object in your module):
uvicorn hello:app --host 127.0.0.1 --port 8000 --reload
- First
hello= module name (hello.py→hello). - Second
app= theFastAPI()instance in that file. --reloadrestarts when you save changes (development only).
2. From main() inside the file (same --host, --port, and --reload flags, parsed in Python):
python hello.py --host 127.0.0.1 --port 8000 --reload
Omit flags to use the defaults (127.0.0.1, port 8000, no reload). Example without reload:
python hello.py --port 9000
Both approaches call Uvicorn under the hood. Use whichever you prefer; the Uvicorn chapter compares them in more detail.
You should see log lines ending with something like Uvicorn running on http://127.0.0.1:8000 (host/port match what you passed).
Check the responses
In another terminal (venv activated is optional for curl):
curl http://127.0.0.1:8000/
Expected bodies:
{"message":"it works!"}
Or open those URLs in a browser. FastAPI also serves interactive docs at http://127.0.0.1:8000/docs.
Stop the server with Ctrl+C when you are done.
Tip
If
uvicornis “command not found”, the venv is probably not activated, or install failed—runwhich uvicorn(orwhere uvicorn) and confirm it points inside.venv.
Your Turn
- Create and activate
.venvin your repo (if you have not already). - Install FastAPI, Uvicorn, HTTPX, and ensure Pydantic is available.
- Confirm
python -c "import fastapi, uvicorn, httpx, pydantic"succeeds. - Add
hello.pywithGET /ping→{"message": "pong"}. - Start the server with
python hello.py --host 127.0.0.1 --port 8000 --reload, then verify both URLs (browser,curl, or/docs). - Commit lockfiles / dependency files your instructor wants—not
.venvitself.hello.pyis optional to commit unless your instructor asks for it.