Python, section 9 of 9, 4h

Environments, packaging and tooling

By the end: You can set up a project somebody else can clone and run correctly first time.

  • Virtual environments, and what they actually do
  • Installing and pinning dependencies
  • Project layout
  • Linting and formatting
  • Reading a traceback

New to python? A programming language is the set of written instructions a computer will follow, and Python is the one this field settled on. It reads close to English: a line that filters a list of records looks roughly like a sentence describing that filter. Every model provider ships a Python library, and nearly every machine learning tool is written in it. Why it matters

Code that runs on your machine and nowhere else is not finished. This section covers what makes a project portable: a virtual environment so each project keeps its own packages and versions, pinned dependencies so a colleague installs exactly what you did, a layout people expect to find, and tools that format and check the code for you. It ends on reading a traceback, which is the single most useful debugging skill in the language.

Virtual environments#

A virtual environment is a folder holding its own copy of Python and its own packages. Each project gets one, so two projects can use different versions of the same library without fighting.

python3 -m venv .venv           # create it
source .venv/bin/activate       # turn it on (Mac and Linux)
.venv\Scripts\activate          # Windows

which python                    # .../project/.venv/bin/python
deactivate                      # turn it off

Activating simply puts that folder first in your PATH, which is the list of places your shell searches for commands. So typing python finds the project copy instead of the system one. That is the whole mechanism.

Why source and not ./

Running a script normally starts a new shell, which would change its own PATH and then exit, losing the change. source runs the commands in your current shell, so the change stays.

Dependencies#

pip install requests
pip install "pydantic>=2.0"
pip freeze > requirements.txt      # record exact versions
pip install -r requirements.txt    # install them elsewhere

Recording exact versions matters more than it seems. Without it, a project that builds today can break in three weeks because a library you never named published an update. The failure arrives in CI on an unrelated change and costs an afternoon.

Project layout#

myproject/
  .venv/              never committed
  .env                secrets, never committed
  .gitignore
  pyproject.toml      project and dependency declaration
  README.md
  src/
    myproject/
      __init__.py
      main.py
  tests/
    test_main.py

Secrets belong in a .env file that is listed in .gitignore, and are read at runtime. An API key committed to a public repository is scanned and abused within minutes.

import os
from dotenv import load_dotenv

load_dotenv()
api_key = os.environ["GEMINI_API_KEY"]

Tooling#

  • ruff: linting and formatting in one tool, fast enough to run every time you save.
  • uv: a much faster replacement for pip and venv, worth adopting on new projects.
  • A type checker in your editor, so annotations help you while you type rather than in CI.
ruff check .          # find problems
ruff check --fix .    # fix what it can
ruff format .         # format everything

Reading a traceback#

Read a traceback from the bottom up. The last line is the actual error. The lines above it are the path of calls that led there, oldest at the top.

Traceback (most recent call last):
  File "main.py", line 12, in <module>
    result = process(data)
  File "process.py", line 8, in process
    return item["name"]
KeyError: 'name'
The error is a missing key, at process.py line 8, reached from main.py line 12.

When the trace runs through library code, find the last line that belongs to you. That is almost always where the problem is, because the library is usually doing exactly what it was told.

Where people go wrong

Installing packages globally with sudo pip install. It mixes project dependencies into the system Python, and eventually two projects need incompatible versions and something you depend on stops working.

If this comes up in an interview

Why use a virtual environment?

It isolates a project's dependencies. Without one, two projects needing different versions of the same library conflict, and installing globally can break system tools that rely on Python.

What is the difference between requirements.txt and pyproject.toml?

requirements.txt is a flat list of packages to install. pyproject.toml declares the project itself, including metadata, dependencies and tool configuration, and is the modern standard.

How do you handle secrets such as API keys?

Keep them in environment variables, loaded from a .env file that is gitignored, and read at runtime. Never commit them. In production they come from the platform's secret store rather than a file.

How do you read a Python traceback?

Bottom up. The last line names the exception. The frames above show the call path. Find the last frame in your own code, because that is usually where the mistake is.

Build this: Set up a project with a virtual environment, a pinned requirements file, a gitignored .env holding a fake API key, and a script that reads that key. Then clone it into a fresh folder and confirm it runs first time.

This is one section of Python, 33 hours across 9 sections. Read it in full to get the whole topic in order.

Stop 1 of 50 on the AI Engineer route

0 of 50 topics done · 0h behind you, 603h to go

Next on this routeHTTP & APIsRequests, status codes, retries, rate limits.8h

What you have marked done is stored in this browser only. It does not reach a server, and clearing site data will clear it.