pip install Local Projects: The Right Way to Do Python Development

Stop the Python path madness! Learn how to properly install local projects with virtual environments, pyproject.toml, and editable installs. Your future self will thank you.

pip install Local Projects: The Right Way to Do Python Development

Let's talk about something that drives every Python developer absolutely bonkers: you're working on a project, you need to test it, and you end up doing something like this:

export PYTHONPATH=$PYTHONPATH:/path/to/my/other/project
python -m my_project.main

Or worse, you're sys.path.append()-ing all over your code like it's 2010.

Stop. Just stop.

There's a better way, and once you see how clean it is, you'll never go back to the path manipulation dark arts again.

🛡️ First Things First: Virtual Environments Are Your Friend

Before we do anything else, let's talk about virtual environments. If you're still installing packages globally, we need to have a serious talk.

# The magic command that saves you countless headaches
python -m venv .venv

What does this actually do? It creates a little bubble for your project. Inside this bubble:

  • You get your own Python interpreter
  • You get your own site-packages directory
  • You can install whatever you want without affecting your system Python
  • You can delete it and start fresh without drama

Activate it like this:

# On macOS/Linux
source .venv/bin/activate

# On Windows (you poor soul)
.venv\Scripts\activate

Now your prompt looks something like (.venv) $, and you're in the safe zone. Any pip install commands you run now only affect this environment.

📋 Enter pyproject.toml: The Modern Python Configuration

Remember the good old days of setup.py? Yeah, me neither. Those were dark times filled with boilerplate and existential dread.

(If you're still using setup.py, then I feel bad for you. 🤪)

Enter pyproject.toml - the clean, modern way to configure your Python projects. Here's what a basic one looks like:

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "my-awesome-project"
version = "0.1.0"
description = "This project will change the world"
authors = [{name = "Your Name", email = "you@example.com"}]
license = {text = "MIT"}
dependencies = [
    "requests>=2.28.0",
    "click>=8.0.0",
]

Why hatchling? Honestly, no deep reason - it's what I learned early on and it just works. It's fast, it's simple, and it doesn't make me want to throw my laptop out the window. That's pretty much my criteria for build tools.

🔄 The Magic: Editable Installs with pip install -e .

Here's where the magic happens.

Side Note: If you've watched any of my YouTube videos (which are kinda old now), it's something I left out. It was just an intro to setting up an environment, but it missed a lot of key things I'm about to cover - I promise I'll do better next time.

Once you have your pyproject.toml set up, you can install your own project as if it were a regular package:

pip install -e .

The -e flag stands for "editable," and it's a game-changer. Here's what happens:

  1. Your project gets installed in your virtual environment - just like any other package
  2. Your imports work everywhere - no more PYTHONPATH gymnastics
  3. Changes are reflected immediately - edit your code, it's instantly available
  4. Namespace is correct - from my_project.utils import helper just works

Let's say you have this structure:

my-awesome-project/
├── pyproject.toml
├── src/
│   └── my_project/
│       ├── __init__.py
│       ├── main.py
│       └── utils.py
└── tests/
    └── test_utils.py

After pip install -e ., you can do this from anywhere:

# In tests/test_utils.py
from my_project.utils import helper_function

# In a completely different script
from my_project.main import main_function

No more relative import nightmares. No more sys.path manipulation. Just clean, working imports.

🔗 Level Up: Multiple Local Projects

Here's where it gets really cool. What if you're working on multiple related projects? Maybe you have:

  • my-data-pipeline (data processing library)
  • my-api-client (API wrapper)
  • my-web-app (the main application)

You can install them all locally and they'll play nice together:

# In your main project directory
pip install -e ../my-data-pipeline
pip install -e ../my-api-client
pip install -e .

Now your main app can import from both:

from my_data_pipeline.transformers import clean_data
from my_api_client.client import APIClient
from my_web_app.routes import app

All the namespaces align perfectly, and you can edit any of these projects and see changes immediately. It's like having your own private PyPI, but without all the hosting overhead.

🔍 Verify Everything: See What You've Installed

Want to make sure everything is installed correctly? Check your work:

# See all installed packages
pip list

# Get details about a specific package
pip show my-awesome-project

The pip show output is particularly helpful:

Name: my-awesome-project
Version: 0.1.0
Summary: This project will change the world
Location: /path/to/your/project/.venv/lib/python3.11/site-packages
Requires: requests, click
Required-by:
Editable project location: /path/to/your/project. 👈 this is the key

Notice that Editable project location line? That's your proof that the -e install worked and changes will be reflected immediately.

NOTE: if you bump the version number in pyproject.toml, you'll need to run pip install -e . again to pick up the version number change. But otherwise the actual code changes are automatically picked up and you don't need to do anything else.

⚠️ Pitfalls and Gotchas (Because Nothing's Perfect)

Let's be real - this approach isn't without its quirks:

The Development Dependency Trap

You'll inevitably want some dependencies that are only for development (pytest, black, etc.). Add them to pyproject.toml:

[project.optional-dependencies]
dev = [
    "pytest>=7.0.0",
    "black>=22.0.0",
    "mypy>=1.0.0",
]

# Install with: pip install -e ".[dev]"

The Circular Import Nightmare

If Project A depends on Project B and Project B depends on Project A, you're in for a world of hurt. The solution? Don't do that. Seriously. Redesign your dependencies (create a shared library for common code).

The Multiple Python Versions Problem

Remember that virtual environment you created? It's tied to a specific Python version. If you switch Python versions, recreate the venv. Don't try to be a hero.

🌟 Other Options (And Why You Might Consider Them)

While pip install -e . with hatchling is my go-to, there are other approaches:

Poetry

Poetry is like the fancy, all-in-one solution. It handles dependencies, virtual environments, and publishing all in one tool. It's beautiful, but sometimes I just want to install a package, not join a cult.

pip-tools

If you like your requirements.txt files but want them auto-generated, pip-tools is fantastic. Compile your dependencies once, deploy with confidence.

conda

If you're doing data science, conda's environment management is hard to beat. It handles Python packages and non-Python packages in the same environment.

Direct Python Path

And yes, you could still mess with PYTHONPATH if you hate yourself. But you made it this far in the article, so I assume you're better than that.

🎯 The Bottom Line

Stop fighting with Python imports and paths. Use virtual environments, embrace pyproject.toml, and install your projects with pip install -e .. Your code will be cleaner, your tests will run reliably, and you won't have to explain to your teammates why they need to set 17 environment variables to run your code.

Now go forth and install your projects the right way. Your future self will thank you.


What's your favorite Python development setup? Drop a comment below and let me know your tricks for avoiding Python path madness!

Comments

Share your thoughts and insights in the comments below. We'd love to hear your perspective on this topic!

Geek Cafe LogoGeek Cafe

Your trusted partner for cloud architecture, development, and technical solutions. Let's build something amazing together.

Quick Links

© 2025 Geek Cafe LLC. All rights reserved.

Research Triangle Park, North Carolina

Version: 8.9.15