I have a object-oriented Python 3.7 project with a structure along the following lines:
├── plugins
│ ├── book_management
│ │ ├── book_inserter.py
│ │ ├── book_remover.py
│ │ ├── __init__.py
│ │ ├── book.py
│ │ ├── book_sampler.py
│ │ ├── operators
│ │ │ ├── __init__.py
│ │ │ ├── register_book.py
│ │ │ ├── unregister_book.py
│ │ │ └── mark_book_as_missing.py
│ ├── __init__.py
│ ├── reader_management
│ │ ├── __init__.py
│ │ ├── reader.py
│ │ ├── reader_creator.py
│ │ ├── reader_emailer.py
│ │ ├── reader_remover.py
│ │ ├── operators
│ │ │ ├── __init__.py
│ │ │ ├── create_reader.py
│ │ │ ├── remove_reader.py
│ │ │ └── email_reader.py
├── tests
│ ├── __init__.py
│ ├── book_management_tests
│ │ ├── __init__.py
│ │ ├── test_book.py
│ │ ├── test_book_inserter.py
│ │ ├── test_book_remover.py
│ │ ├── test_book_sampler.py
│ │ ├── test_mark_book_as_missing_operator.py
│ │ ├── test_register_book_operator.py
│ │ ├── test_unregister_book_operator.py
│ ├── reader_management_tests
│ │ ├── __init__.py
│ │ ├── test_reader.py
│ │ ├── test_reader_creator.py
In a test like test_mark_book_as_missing_operator
I end up having imports like:
from plugins.book_management.book_inserter import BookInserter
from plugins.book_management.operators.mark_book_as_missing import (
MarkBookAsMissingOperator
)
from plugins.reader_management.reader_creator import ReaderCreator
from plugins.reader_management.operators.create_reader import (
CreateReaderOperator
)
This feels really bad having these really verbose partial imports. So I am guessing I must be doing it wrong. Ideally, importing plugins.reader_management
and plugins.reader_management.operators
possibly as something shorter would seem much more readable.
book_inserter.py
is defining a single class BookInserter
. Ideally, I would like to keep this 1-class / 1-file structure. Obvisouly, this leads to an inflation of the number of files but also allows of shorter more focused files. But if this is deeply non-Pythonic I am willing to hear why and how I should adapt the code structure.
Finally I have been using this kind of several layer architectures (plugins/*_management/operators/*.py
) but this leads to very long import lines, and I am frequently having legitimate lint issues as a result.
I have been considering importing submodules from top modules (like book_management, in book_management/__init__.py
) but I am not sure if it is good practice and also it seems like a violation of the principle of not having unused imports in your files. (Also would I be at risk of circular imports as a result?)
My main question in short: what would be a(the?) Pythonic way to structure such a project and setup the imports (with ideally some justification of why this would be a/the Pythonic way to do it).