Search code examples
pythondomain-driven-designclean-architecture

Import project's subpackages in Python


i'm experimenting with DDD in Python so i've decided to implement a toy project.

I've created different directories in other to separate shared concepts from specific bounded contexts concepts.

As i try to import these files, i'm facing a No module named error exceptions

For example, with this project structure:

.
└── src/
    ├── Book/
    │   ├── application
    │   ├── domain/
    │   │   ├── Book.py
    │   │   └── __init__.py
    │   ├── infrastructure
    │   └── __init__.py
    └── Shared/
        ├── application
        ├── domain/
        │   ├── Properties/
        │   │   ├── __init__.py
        │   │   └── UuidProperty.py
        │   ├── ValueObjects/
        │   │   ├── __init__.py
        │   │   └── BookId.py
        │   └── __init__.py
        └── infrastructure

On src/Book/domain/Book.py i have:

from Shared.domain.ValueObjects.BookId import BookId


class Book:
    bookId: BookId
    pages: int

As i've seen in other answer (pretty old ones) it can be fixed by adding these folders to PYTHONPATH or PATH like sys.path.insert(*path to file*) but i'm wondering if there is a more pythonic way to achieve that.

I've also tried to add an __init__.py file to src and import as from src.Shared.domain.ValueObjects.BookId import BookId but none of previous attempts worked for me

On other repos i've saw that they use setuptools to install the src package in order to import it at unit tests (i cant either import them at tests), but i don't know if that is recommended or would work inside package imports


Solution

  • In case someone is facing the same issue as me, i managed to import subpackages and the full package in tests directory.

    Just include, in each subpackage, an __init__.py file, and inside the package/subpackages, use relative imports (it looses semantic of imports, when we know where each imports comes from by absolute path from root directory, but works)

    from ..Properties import UuidProperty
    
    # inside __init__.py of Properties directory
    
    from .UuidProperty import UuidProperty
    

    And, by including an __init__.py inside src/ we could import them at tests directory like

    from src.Book.domain import Book
    

    Hope this helps someone!