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 offActivating 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 elsewhereRecording 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.pySecrets 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 everythingReading 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'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.
Watch it explained
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
What you have marked done is stored in this browser only. It does not reach a server, and clearing site data will clear it.