How I set up a Python AI project
How to guide to follow my local setup

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
pipandvenv. 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.

