LINUX.ORG.RU

Питон, автоимпорт коллекции модулей

 , ,


0

1

Есть коллекция модулей, по сути это разные обработчики с одним интерфейсом.

processors/foo.py:
class FooProcessor:
    ...

processors/bar.py:
class BarProcessor:
    ...

processors/baz.py:
class BazProcessor:
    ...

processors/__init__.py:
from .foo import FooProcessor
from .bar import BarProcessor
from .baz import BazProcessor

И испольузется это так:

from processors import *

def spawn(name):
    classname = name + "Processor"
    return globals()[classname]()

spawn("Foo")

Так вот, надоело все процессоры регистрировать в __init__.py, криво это да и всякие линтеры ругаются на неиспользуемые модули.

Вопрос: как это сделать красиво?

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

Наверное можно в spawn руками импортировать модуль по имени, но имя класса не всегда совпадает с именем модуля (и в модуле может вообще быть несколько классов).

Наверное можно запихнуть все модули в modname/__init__.py, но это неудобно и криво.

Наверное можно в processors/__init__.py перебрать модули в processors и импортировать их все - есть пример как это сделать?

Может есть ещё красивее способ?

★★★★★

надоело все процессоры регистрировать

у тебя их там сотни что ли?

from processors import *

никогда так не делай. в твоём случае правильно так

import processors

def spawn(name):
	classname = name + "Processor"
	return getattr(processors, classname)()

eternal_sorrow ★★★★★
()
Последнее исправление: eternal_sorrow (всего исправлений: 2)
Ответ на: комментарий от eternal_sorrow

у тебя их там сотни что ли?

Ну полсотни есть.

никогда так не делай

Почему? Не, я знаю почему так не надо в общем случае, но тут же явно импортируются конкретные классы.

в твоём случаеправильно так

А import processors разве заимпортирует сразу и подмодули?

slovazap ★★★★★
() автор топика

Ужос какой, я наверное зря подумал, что питон хороший язык..

Apache2017
()
Ответ на: комментарий от slovazap

Почему?

имеется в виду from ... import *. потому что это засоряет область видимости

А import processors разве заимпортирует сразу и подмодули?

нет, он импортирует всё что прописано в __init__.py в область видимости processors (или другую если добавишь as name)

eternal_sorrow ★★★★★
()
Последнее исправление: eternal_sorrow (всего исправлений: 1)

лучше наведи порядок в твоём приложении, с ним явно что то не так, если модуль содержит полсотни семантически схожих классов

eternal_sorrow ★★★★★
()
Ответ на: комментарий от slovazap

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

eternal_sorrow ★★★★★
()

Импортируй динамически только нужны подмодули с помощью __import__

Либо из processors, либо напрямую по имени файла (но тогда наведи порядок в именах)

Crocodoom ★★★★★
()
Ответ на: комментарий от eternal_sorrow

from foo import bar прописаны в __init__.py, я не собираюсь их дублировать.

slovazap ★★★★★
() автор топика
Ответ на: комментарий от eternal_sorrow

Мне виднее, и я описал это в условиях задачи как данное. Вопрос был про другое.

slovazap ★★★★★
() автор топика

Всё-таки мне интересно решение без импорта в spawn.

Для начала, правильно ли я понимаю что без явного импорта всех модулей не обойтись? Если да, то мне видится такой вариант: в processors/__init__.py нужно добавить механизм находящий все модули и импортирующий их, и там же будет определяться фабрика. Соответственно в клиентском коде импортируем только фабрику и работаем с ней.

slovazap ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.