Python Project Setup: venv, Dependencies, and Package Structure

#Poetry #Project Structure #Python #uv #virtualenv

One of the first hurdles developers face when starting with Python is organizing their project structure and managing dependencies cleanly. Unlike frameworks with standardized scaffolding (like Laravel or Rails), Python gives developers full freedom. However, unorganized project setups lead to circular import bugs, broken imports in production, and dependency conflicts.

This guide establishes a production-standard Python project setup step by step.

1. The Standard src Layout

The src layout is the recommended directory structure for modern Python applications and microservices. It prevents accidental imports of uninstalled local packages and forces clean packaging boundary checks.

my_python_app/
โ”œโ”€โ”€ src/
โ”‚   โ””โ”€โ”€ my_app/
โ”‚       โ”œโ”€โ”€ __init__.py
โ”‚       โ”œโ”€โ”€ main.py
โ”‚       โ”œโ”€โ”€ config.py
โ”‚       โ”œโ”€โ”€ api/
โ”‚       โ”‚   โ”œโ”€โ”€ __init__.py
โ”‚       โ”‚   โ””โ”€โ”€ routes.py
โ”‚       โ”œโ”€โ”€ services/
โ”‚       โ”‚   โ””โ”€โ”€ user_service.py
โ”‚       โ””โ”€โ”€ models/
โ”‚           โ””โ”€โ”€ user.py
โ”œโ”€โ”€ tests/
โ”‚   โ”œโ”€โ”€ __init__.py
โ”‚   โ”œโ”€โ”€ test_routes.py
โ”‚   โ””โ”€โ”€ test_services.py
โ”œโ”€โ”€ .gitignore
โ”œโ”€โ”€ README.md
โ””โ”€โ”€ pyproject.toml

2. Managing Dependencies with Poetry or uv

Legacy Python projects relied on requirements.txt and manual venv creation. Modern production projects use pyproject.toml managed by Poetry or uv (an extremely fast Python package installer written in Rust).

Using Poetry:

# Initialize project
poetry init

# Add dependencies
poetry add fastapi uvicorn pydantic pydantic-settings
poetry add pytest httpx --group dev

# Run application inside virtualenv
poetry run uvicorn src.my_app.main:app --reload

Using uv (Lightning Fast Alternative):

# Create virtualenv instantly
uv venv

# Activate environment
source .venv/bin/activate

# Install dependencies at high speed
uv pip install fastapi uvicorn pydantic

3. Environment Configuration with Pydantic BaseSettings

Never hardcode API keys or database URLs. Use pydantic-settings to parse environment variables safely with strict type validation.

# src/my_app/config.py
from pydantic_settings import BaseSettings

class Settings(BaseSettings):
    app_name: str = "My Python API"
    environment: str = "development"
    database_url: str
    openai_api_key: str

    class Config:
        env_file = ".env"

settings = Settings()

If DATABASE_URL is missing from the .env file, the app fails to start immediately on launch with an explicit error message, preventing runtime crashes halfway through execution.

Summary

By using the src/ directory layout, locking dependencies with pyproject.toml (via Poetry or uv), and enforcing settings with Pydantic, your Python project is organized, reproducible, and ready for production deployment.

Need guidance setting up scalable Python microservices? Check out my AI integration services or Hire Python Developer.


Prakash Tank

Prakash Tank

Full-Stack Architect & Tech Enthusiast. Passionate about building scalable applications and sharing knowledge with the community.