Skip to main content

Command Palette

Search for a command to run...

How I set up a Python AI project

How to guide to follow my local setup

Updated
6 min read
How I set up a Python AI project

This is my opinionated guide to setting up a Python AI project from scratch. There are plenty of alternatives out there, but this is what's been working well for me.


The Tools

Two things to install before anything else:

  • uv — a blazing-fast Python package manager that replaces both pip and venv. It handles Python versions, dependencies, and virtual environments in one tool.

  • VSCode — my editor of choice. Free, extensible, and excellent Python support. Pycharm is also excellent but for most of my learnings VSCode has been sufficient.

Installing uv

On macOS or Linux, one line in your terminal:

curl -LsSf https://astral.sh/uv/install.sh | sh

On Windows (PowerShell):

powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

Check it's working:

uv --version

Getting Python 3.12

Here's something I love about uv — you don't need a separate Python installation. uv manages Python versions for you:

uv python install 3.12

Verify it's there:

uv python list

That's it. No fighting with system Python, no Homebrew conflicts, no PATH headaches. If you've heard of pyenv as an alternative, it's a solid tool, but for most beginners it's one extra thing to learn. uv does it all.

Why Python 3.12? It's stable, widely supported, and every major AI/ML library works with it. Safe choice.


Creating a New Project

Navigate to wherever you keep your code and run:

uv init my-project
cd my-project

uv scaffolds a clean project structure for you:

my-project/
├── .python-version   # pins the Python version
├── pyproject.toml    # project config & dependencies
├── README.md
└── main.py

pyproject.toml is the modern Python standard for project configuration — think of it as the project's passport. It declares the project name, which Python version it needs, and all its dependencies.


Pinning the Python Version

Inside the project folder, tell uv to use 3.12:

uv python pin 3.12

This writes 3.12 into the .python-version file. Now anyone who clones the repo uses the exact same version. No more "it works on my machine" surprises.


Creating the Virtual Environment

A virtual environment isolates your project's packages from everything else on your machine. Without one, installing packages globally causes version conflicts across projects — it gets messy fast.

With uv, setup is a single command:

uv sync

This creates a .venv/ folder inside your project and installs all declared dependencies. The key thing: you never need to activate it manually. Use uv run to execute scripts and it handles the virtual environment automatically.


Opening in VSCode

code .

When VSCode opens, it might prompt you to "Select a Python Interpreter". Choose the one inside .venv — it'll show a path like ./venv/bin/python. This connects VSCode to your project's isolated environment.


Two Extensions Worth Installing

Open the Extensions panel (Cmd+Shift+X on Mac, Ctrl+Shift+X on Windows) and add these two:

Python by Microsoft — syntax highlighting, IntelliSense, the ability to run and debug Python files. Essential.

Ruff by Astral Software — a linter and formatter that keeps your code consistent. It catches errors before you run code and auto-formats on save. I use this on every project.


Adding Dependencies

Now for the actual project dependencies. I add two to every AI project:

Ruff for linting:

uv add ruff

python-dotenv for loading environment variables from a .env file:

uv add python-dotenv

Both commands automatically update pyproject.toml and uv.lock. Your config will look something like this:

[project]
name = "my-project"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = [
    "python-dotenv>=1.0.0",
    "ruff>=0.9.0",
]

uv.lock records the exact versions of every installed package. Commit this file — it makes the project perfectly reproducible on any machine.


Handling API Keys Safely

This one matters a lot. AI projects almost always need API keys — for OpenAI, Anthropic, LangSmith, etc. You must never commit these to git.

My approach uses two files:

  • .env.example — committed to the repo, contains placeholder values showing what keys are needed

  • .env — your real local file with actual secrets, never committed

Start by copying the example:

cp .env.example .env

Then open .env and fill in your real keys:

OPENAI_API_KEY="your-real-key-here"
ANTHROPIC_API_KEY="your-real-key-here"

Why is this safe?

The .gitignore file contains .env, which instructs git to completely ignore that file. It never gets staged, never gets committed, never ends up on GitHub. Your secrets stay local.

Loading the keys in Python

With python-dotenv installed, two lines at the top of any file is all you need:

from dotenv import load_dotenv
import os

load_dotenv()

api_key = os.getenv("OPENAI_API_KEY")

load_dotenv() reads the .env file and makes those variables available via os.getenv().


Running Your Code

Use uv run instead of calling python directly:

uv run main.py

uv run automatically picks up the virtual environment — no activation step needed.


What You End Up With

After following these steps, your project looks like this:

my-project/
├── .env              # ← your secrets (git-ignored, never commit this)
├── .env.example      # ← template showing required variables (commit this)
├── .gitignore        # ← tells git what to ignore
├── .python-version   # ← pins Python 3.12
├── .venv/            # ← virtual environment (git-ignored)
├── main.py
├── pyproject.toml    # ← project config and dependencies
└── uv.lock           # ← exact dependency versions (commit this)

Clean, reproducible, and safe. Every example in my AI Notebook repo follows this exact structure.


Quick Reference

Task Command
Create new project uv init my-project
Pin Python version uv python pin 3.12
Install / sync dependencies uv sync
Add a dependency uv add <package>
Run a script uv run main.py
Copy env template cp .env.example .env

This is my personal starting point for every AI learning experiment I run. It's opinionated, but it's fast to set up and gets out of the way so I can focus on what actually matters — the code.

Always open to feedback and suggestions for alternatives or improvements. But so far, this setup has been working well for me. 🚀

This post is part of my AI Notebook series — documenting my journey learning AI and agentic systems, one step at a time.