Python Project Structure
Seth HobsonCommunityCreated by Seth Hobson
- Skill
- Guidelines
- Software development
- MIT
- No issues found
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
This skill provides a framework for designing maintainable Python project structures. It covers module cohesion, directory hierarchy, naming conventions, and the use of __all__ to define public interfaces. It offers patterns for layered and domain-driven architectures, test organization, and import strategies to ensure code remains discoverable and predictable.
What it does
- Defines strategies for grouping related code into cohesive modules.
- Provides patterns for creating explicit public APIs using __all__.
- Recommends directory structures ranging from flat hierarchies to domain-driven layouts.
- Outlines conventions for file naming and absolute import usage.
- Suggests approaches for organizing test files relative to production code.
- Offers guidance on when to split files based on complexity and responsibility.
When to use it
- When initiating a new Python project from scratch.
- When refactoring an existing codebase to improve clarity.
- When defining the public interface for a library or package.
- When deciding between flat and nested directory structures.
- When establishing consistent conventions for team-based development.
Advantages
- Promotes consistent organization across the codebase.
- Clarifies which parts of a module are intended for public use.
- Reduces import complexity through absolute paths and flat hierarchies.
- Supports separation of concerns through layered or domain-driven designs.
Usage examples
- “How should I structure a new Python project?”
- The agent provides a standard directory layout using a src/ folder, separating source code from tests, and suggests using a flat structure for modules.
- “How do I hide internal helper functions in my Python package?”
- The agent explains how to use the __all__ list in __init__.py to explicitly export only the intended public classes and functions.
- “Should I use relative or absolute imports?”
- The agent recommends absolute imports for better reliability and clarity, explaining that relative imports can break during refactoring.
- “How should I organize my tests?”
- The agent presents two options: colocated tests for proximity or a parallel tests/ directory for separation, advising consistent application of the chosen method.
Install
Download the skill as a ZIP:
https://mp-staging.autogineer.com/agent-skills/wshobson/python-project-structure/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip python-project-structure.zip -d .agents/skills
Documentation by Seth Hobson
Python Project Structure & Module Architecture
Design well-organized Python projects with clear module boundaries, explicit public interfaces, and maintainable directory structures. Good organization makes code discoverable and changes predictable.
When to Use This Skill
Starting a new Python project from scratch
Reorganizing an existing codebase for clarity
Defining module public APIs with
__all__Deciding between flat and nested directory structures
Determining test file placement strategies
Creating reusable library packages
Core Concepts
1. Module Cohesion
Group related code that changes together. A module should have a single, clear purpose.
2. Explicit Interfaces
Define what's public with __all__. Everything not listed is an internal implementation detail.
3. Flat Hierarchies
Prefer shallow directory structures. Add depth only for genuine sub-domains.
4. Consistent Conventions
Apply naming and organization patterns uniformly across the project.
Quick Start
myproject/
├── src/
│ └── myproject/
│ ├── __init__.py
│ ├── services/
│ ├── models/
│ └── api/
├── tests/
├── pyproject.toml
└── README.mdFundamental Patterns
Pattern 1: One Concept Per File
Each file should focus on a single concept or closely related set of functions. Consider splitting when a file:
Handles multiple unrelated responsibilities
Grows beyond 300-500 lines (varies by complexity)
Contains classes that change for different reasons
# Good: Focused files
# user_service.py - User business logic
# user_repository.py - User data access
# user_models.py - User data structures
# Avoid: Kitchen sink files
# user.py - Contains service, repository, models, utilities...Pattern 2: Explicit Public APIs with __all__
Define the public interface for every module. Unlisted members are internal implementation details.
# mypackage/services/__init__.py
from .user_service import UserService
from .order_service import OrderService
from .exceptions import ServiceError, ValidationError
__all__ = [
"UserService",
"OrderService",
"ServiceError",
"ValidationError",
]
# Internal helpers remain private by omission
# from .internal_helpers import _validate_input # Not exportedPattern 3: Flat Directory Structure
Prefer minimal nesting. Deep hierarchies make imports verbose and navigation difficult.
# Preferred: Flat structure
project/
├── api/
│ ├── routes.py
│ └── middleware.py
├── services/
│ ├── user_service.py
│ └── order_service.py
├── models/
│ ├── user.py
│ └── order.py
└── utils/
└── validation.py
# Avoid: Deep nesting
project/core/internal/services/impl/user/Add sub-packages only when there's a genuine sub-domain requiring isolation.
Pattern 4: Test File Organization
Choose one approach and apply it consistently throughout the project.
Option A: Colocated Tests
src/
├── user_service.py
├── test_user_service.py
├── order_service.py
└── test_order_service.pyBenefits: Tests live next to the code they verify. Easy to see coverage gaps.
Option B: Parallel Test Directory
src/
├── services/
│ ├── user_service.py
│ └── order_service.py
tests/
├── services/
│ ├── test_user_service.py
│ └── test_order_service.pyBenefits: Clean separation between production and test code. Standard for larger projects.
Advanced Patterns
Pattern 5: Package Initialization
Use __init__.py to provide a clean public interface for package consumers.
# mypackage/__init__.py
"""MyPackage - A library for doing useful things."""
from .core import MainClass, HelperClass
from .exceptions import PackageError, ConfigError
from .config import Settings
__all__ = [
"MainClass",
"HelperClass",
"PackageError",
"ConfigError",
"Settings",
]
__version__ = "1.0.0"Consumers can then import directly from the package:
from mypackage import MainClass, SettingsPattern 6: Layered Architecture
Organize code by architectural layer for clear separation of concerns.
myapp/
├── api/ # HTTP handlers, request/response
│ ├── routes/
│ └── middleware/
├── services/ # Business logic
├── repositories/ # Data access
├── models/ # Domain entities
├── schemas/ # API schemas (Pydantic)
└── config/ # ConfigurationEach layer should only depend on layers below it, never above.
Pattern 7: Domain-Driven Structure
For complex applications, organize by business domain rather than technical layer.
ecommerce/
├── users/
│ ├── models.py
│ ├── services.py
│ ├── repository.py
│ └── api.py
├── orders/
│ ├── models.py
│ ├── services.py
│ ├── repository.py
│ └── api.py
└── shared/
├── database.py
└── exceptions.pyFile and Module Naming
Conventions
Use
snake_casefor all file and module names:user_repository.pyAvoid abbreviations that obscure meaning:
user_repository.pynotusr_repo.pyMatch class names to file names:
UserServiceinuser_service.py
Import Style
Use absolute imports for clarity and reliability:
# Preferred: Absolute imports
from myproject.services import UserService
from myproject.models import User
# Avoid: Relative imports
from ..services import UserService
from . import modelsRelative imports can break when modules are moved or reorganized.
Best Practices Summary
Keep files focused - One concept per file, consider splitting at 300-500 lines (varies by complexity)
Define
__all__explicitly - Make public interfaces clearPrefer flat structures - Add depth only for genuine sub-domains
Use absolute imports - More reliable and clearer
Be consistent - Apply patterns uniformly across the project
Match names to content - File names should describe their purpose
Separate concerns - Keep layers distinct and dependencies flowing one direction
Document your structure - Include a README explaining the organization
Files
- ATTRIBUTION.mdAdded by AutoGineer1008 B
- LICENSELicence file added by AutoGineer1.0 KiB
- SKILL.md6.6 KiB
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Needs: Needs Python
Security
No issues found by our static scan· No issues found
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Created by
- Seth Hobson
- Publisher
- Seth Hobson (Community)
- Source
- wshobson/agents · plugins/python-development/skills/python-project-structure · commit 4bde316
- Licence
- MIT License (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by Seth Hobson.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download python-project-structure.zip