Автоматизация импорта из Python моделей каталога (from * import *)

Если вам надоело писать в __init__.py для каждого файла пакета

from foo import *
from bar import *

У меня есть простой код, автоматизирующий это.

Но давайте вначале разберемся, зачем такое писать вовсе? Во многих случаях это просто плохой стиль, которого я рекомендую вам избегать. Вы смешиваете в пространстве имен имена из других модулей и потом в этой каше очень просто наделать труднообнаружимых ошибок.

Но допустим у вас есть проект, где все модели аккуратно разложены в отдельные файлы (например потому что их много, а также чтобы изменение в разных моделях не изменяло один файл, что обычно усложняет git merge)

- model.py
    - user.py
        class User(Base):
            ...
    - order.py
        class Order(Base):
            ...

Мне далее было бы удобнее писать так

- controllers.py
    - add_user.py
        from model import User, Order
        def add_user(user: User, order: Order):
            ...

Но придется

- controllers.py
    - create_order.py
        from model.user import User
        from model.order import Order
        def add_user(user: User, order: Order):
            ...

Кошмар..

Исправить конечно не сложно - добавим __init__.py:

- model.py
    - __init__.py
        from .user import *
        from .order import *
    - user.py
        class User(Base):
            ...
    - order.py
        class Order(Base):
            ...

Но как же занудно потом не забывать добавлять такие import строчки для каждой новой модели.

Стоп! Это же Python - автоматизировать можно абсолютно что угодно!

Код ниже автоматизирует нужный нам from * import *.

На строке 8 перебираем файлы пакета используя Path.globe().

На строке 9 проверяем что это не подкаталог и что имя не начинается с подчеркивания (чтобы исключить __init__.py и прочие файлы имя которых вы можете начать с подчеркивания, чтобы они не участвовали в этой магии).

Строка 10 импортирует очередной файл как модуль Python используя относительное имя (видите точку в начале имени?).

Строка 11 получает список всех не служебных имен модуля.

И наконец на строке 12 добавляем все имена из модуля в наш __init__.py.