Python for AI engineers: what you actually use

GuideLast reviewed Oct 16, 2026By Himanshu Ramchandani
Short answer

For AI engineering, you need Python well enough to build and debug a small application on your own: virtual environments and packages, lists and dictionaries, functions with type hints, error handling, reading and writing files, modules and packages, classes, and decorators. You don't need advanced Python features before your first builds. Learn the basics properly, then learn the rest when a build asks for it.

Why Python for AI engineering

You can build AI systems in many languages, but I recommend everyone start with Python, for three reasons.

The first is the community. Python has a huge community of developers around the world, so when you are stuck with an error, someone has almost always faced the same error and written about it. That matters more than people think, because when you can't find an answer quickly, you lose motivation, and when you can, you keep going.

The second is that Python is easy to read. Even if you have never seen a Python program, you can usually guess what it does from the words in it, and your guess will be right most of the time.

The third is that Python is a high-level language, which means it follows abstraction, showing you only what is essential. Think about an ATM. You see the screen, the keypad and the cash slot, and you don't see how your balance is stored, how your PIN is checked or how the machine talks to the bank. Python works the same way, so you work with variables and functions, and the memory management and machine instructions stay hidden behind the scenes.

On top of that, almost every AI library and model SDK ships for Python first: PyTorch, TensorFlow, Hugging Face, LangChain, LlamaIndex, and the official SDKs of OpenAI, Anthropic and Google. So most examples, documentation and answers you find will be in Python.

Why learn Python when coding tools can write it

A common question is why you should learn Python at all, when Claude Code, Cursor, Gemini and ChatGPT can write it for you.

These tools can write a lot of code, and I use them every day. But they still have real limitations, and working with them on a bigger project can be painful. They forget earlier instructions as the context fills up, they make changes you didn't ask for, and they sometimes fix one error by creating another.

The way to use them well is to understand the design of your solution, divide it into small parts, and assign those parts to the tool, which then does the job of a junior developer for you. That only works if you can read what the tool wrote and judge whether it is correct. If you don't understand the code, it becomes very difficult to build anything meaningful out of it, and you can't explain your own project in an interview.

So if you call yourself an engineer, take the hard way first and learn the language. You can always use the tools on top of it.

How Python runs your code

When you write Python, you write source code in a file with the .py extension, in words that you can read. When you run it, Python first compiles it into bytecode, a lower-level set of instructions meant for the machine, not for you, and stores it in .pyc files inside a folder called __pycache__. Then the Python interpreter executes that bytecode line by line.

Other languages follow a similar idea with different extensions: C source code becomes a compiled binary, C++ produces object files, and so on. You don't need to work with bytecode directly, but knowing it exists explains two things you will see often: the __pycache__ folders that appear in your projects (which you never commit to Git), and why an error in your code only shows up when Python reaches that line.

Setting up your tools

To start, you need Python itself and an editor.

For learning, Jupyter Notebook is a good place to begin, because you can run one cell at a time, see the output immediately, and keep notes, images and code together. The easiest way to get it is Anaconda Navigator, which installs Python, Jupyter Notebook, VS Code, Spyder and other tools in one place. Google Colab gives you notebooks in the browser with free GPUs, which is useful later for models.

For projects, move to VS Code (or another editor you like) and plain .py files as soon as you can. Notebooks are good for exploring, but production code lives in files and folders, runs from the terminal, and is tested and deployed as a project.

One more tool I use from the first session is a simple drawing tool like Excalidraw. Before writing code for any solution, draw the flow: what the user does, what happens next, and what the system returns, just like the flow of using an ATM. That drawing becomes your plan, and later it becomes the architecture diagram in your README.

Virtual environments

This is the first thing to learn properly, because almost every "it doesn't work" problem in the first weeks comes from environments.

A virtual environment is a folder that holds the Python version and all the libraries for one project. Every library you install is built by a different group of developers, and each one releases new versions on its own schedule, so a new version of one library can break another. If you install everything globally on your system, all your projects share the same libraries, and upgrading something for one project can break another.

So every project gets its own environment.

python3 -m venv venv
source venv/bin/activate
pip install --upgrade pip
pip install fastapi uvicorn python-dotenv
pip freeze > requirements.txt

On Windows, activate with venv\Scripts\activate instead of the source command.

Once the environment is activated, the terminal shows its name, and everything you install goes into that folder instead of your system. If you open the folder, you will find a site-packages directory where every library ends up, along with the libraries those libraries depend on, which is why installing one package often installs ten.

The requirements.txt file lists every package and its exact version. Anyone else, or a server, can recreate the same environment with one command:

pip install -r requirements.txt

Three rules to follow from day 1:

  • Create a new environment for every project.
  • Never commit the environment folder to Git. Commit requirements.txt instead, and let each machine install its own copy.
  • Update requirements.txt every time you install something new.

In our sessions, I use the virtualenv package or the built-in venv module. Newer tools like uv do the same job much faster and manage Python versions too, and they are worth trying once you understand what an environment is.

Python you will use most

AI applications are mostly about moving data around: text in, JSON out, lists of documents, dictionaries of settings, logs written to files. So the parts of Python you use most are the ones that handle data.

Variables and data types

Strings, integers, floats, booleans and None are the basics. In AI work you will use strings constantly, so learn f-strings for building text and the common string methods like split, strip, lower, replace and join.

name = "invoice_042.pdf"
pages = 7
cost_per_page = 0.002

summary = f"{name} has {pages} pages and costs ${pages * cost_per_page:.3f} to process"
print(summary)

Lists, dictionaries, tuples and sets

Lists hold ordered collections, like chunks of a document or a batch of prompts. Dictionaries hold key and value pairs, and they matter most, because JSON, API requests, API responses, model settings and tool arguments are all dictionaries once they reach your Python code. Tuples are like lists that can't be changed, and sets hold unique values, which is useful for removing duplicates.

messages = [
    {"role": "system", "content": "You answer questions about company policy."},
    {"role": "user", "content": "How many leave days do I get?"},
]

messages.append({"role": "assistant", "content": "You get 24 days of paid leave."})

for message in messages:
    print(message["role"], "->", message["content"])

That list of dictionaries is exactly the shape most LLM APIs expect for a conversation, so if you are comfortable with it, you are comfortable with half of every chat application.

Loops and comprehensions

You will loop over files, chunks, test cases and results all the time. List and dictionary comprehensions let you do it in one readable line.

chunks = ["  Leave policy  ", "", "Travel policy", "   "]
clean = [c.strip() for c in chunks if c.strip()]
lengths = {c: len(c) for c in clean}
print(clean, lengths)

Functions and type hints

Functions are how you split a build into parts you can test. Add type hints from the start, because they make your code easier to read, editors use them to catch mistakes, and libraries like FastAPI and Pydantic use them to validate data.

def estimate_cost(input_tokens: int, output_tokens: int, input_price: float, output_price: float) -> float:
    return (input_tokens * input_price + output_tokens * output_price) / 1_000_000


print(estimate_cost(1200, 300, 0.30, 2.50))

Errors and exceptions

Real AI applications fail all the time: the network drops, an API returns an error, a file is missing, the model returns something that isn't valid JSON. try and except let you decide what happens instead of crashing.

import json

raw = '{"name": "Asha", "role": "engineer"'

try:
    data = json.loads(raw)
except json.JSONDecodeError as error:
    print(f"Model returned invalid JSON at position {error.pos}")
    data = None

Catch specific exceptions, not every exception, so you don't hide bugs you need to see.

Files and paths

You will read documents, write logs and save results constantly. Use pathlib for paths and with blocks for files, so files are always closed properly.

from pathlib import Path

docs = Path("data/docs")
docs.mkdir(parents=True, exist_ok=True)

(docs / "note.txt").write_text("Refunds take 5 to 7 working days.")

for path in docs.glob("*.txt"):
    with path.open() as f:
        print(path.name, f.read())

The os and shutil modules do similar work for folders. For example, if you have 10000 images to sort into training and test folders, you don't drag and drop them by hand, you write a short script that creates the folders and moves the files.

Modules and packages

A module is simply a Python file, and you can import anything defined in it into another file. A package is a folder of modules with an __init__.py file inside it, which can be empty and only tells Python to treat the folder as a package. NumPy and pandas are packages, and you can create your own the same way, and even publish them to the Python Package Index (PyPI) so others can install them with pip.

my_project/
    app/
        __init__.py
        llm.py
        tracker.py
    main.py
from app.tracker import track_tokens

Splitting your code into modules early, like one file for model calls, one for token tracking and one for the API, makes everything easier to test and change.

Classes and objects

Object-oriented programming organises code around objects. Think of a player in a game like Subway Surfers: the player is an object, it has attributes like position and score, and it has methods like jump and roll. A class is the blueprint, and each object is one instance of it.

In AI work, you use classes all the time even if you don't write many yourself: an API client is an object, a FastAPI app is an object, a Pydantic model is a class, and a PyTorch model is a class that inherits from nn.Module.

class TokenTracker:
    def __init__(self) -> None:
        self.calls = 0
        self.total_tokens = 0

    def record(self, input_tokens: int, output_tokens: int) -> None:
        self.calls += 1
        self.total_tokens += input_tokens + output_tokens


tracker = TokenTracker()
tracker.record(1200, 300)
print(tracker.calls, tracker.total_tokens)

A simple rule: when you have data and the functions that work on that data together, a class is a good fit. When you only have a function, keep it a function.

Decorators

A decorator adds behaviour to an existing function without changing the function itself. You will meet them first in FastAPI, where @app.get("/health") registers a function as an API route, and later in tools that log, retry or time your functions.

import time
from functools import wraps


def timed(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        start = time.perf_counter()
        result = func(*args, **kwargs)
        print(f"{func.__name__} took {time.perf_counter() - start:.2f}s")
        return result
    return wrapper


@timed
def summarise(text: str) -> str:
    return text[:50]


summarise("A long document about refunds and returns policy for customers.")

A project structure for AI builds

When you move from notebooks to projects, use the same basic structure every time, so you and anyone reading your repo always know where things are.

my-ai-project/
    app/
        __init__.py
        main.py
        llm.py
        prompts/
    tests/
    data/
    .env
    .env.example
    .gitignore
    requirements.txt
    README.md

The .env file holds your keys and never goes to Git, while .env.example shows which variables are needed, with empty values. The secrets page explains this in detail.

NumPy and pandas

Two libraries deserve a mention here because you will use them in many builds. NumPy gives you fast arrays and the math on them, and every embedding you work with is a NumPy array or something very similar. pandas gives you tables (DataFrames) for loading CSV and Excel files, cleaning data, and analysing results like your evaluation scores. Learn the basics of both when your first build needs them, usually when you start working with embeddings or evaluation results.

What you can skip for now

Python is a big language, and some parts can wait until much later:

  • Metaclasses and descriptors.
  • Deep multiple inheritance.
  • Writing C extensions.
  • GUI libraries like Tkinter.
  • Memorising every built-in function.

What you shouldn't skip is reading error messages. A Python traceback tells you the file, the line and the type of error, and reading it carefully, from the bottom up, solves most problems before you need to search anything.

How to practise

Watching someone write Python doesn't teach you Python. For each topic, write the examples yourself, then solve a few small problems without looking at a solution, and only then compare your solution with someone else's. In the 75 day challenge, every day had problem statements with only the expected answers shared, never the solutions, so people had to work them out and discuss their approaches with each other.

From the floor

Day 1 of the 75 day AI engineering challenge was Python and nothing else, with a Python master class video, a text version of it, and practice problems. The second thing I asked everyone to do on day 1 was create a GitHub account, because every piece of code they wrote after that would go there.

When I explained classes in one session, I started with a game instead of the definition, because everyone has played one, and once you see that the player is an object with a position, a score and actions it can take, the idea of attributes and methods makes sense before you see any syntax.

Next step

Read working with LLM APIs and make your first model call.

Sources