Я хотел бы зарегистрировать класс (не экземпляр) при его создании ... но без его импорта.
В основном, я хочу сделать то, что описано здесь:
Как автоматически зарегистрировать класс, когда он определен
... но без необходимости импортировать зарегистрированный класс в любом месте.
Вот проблема: в определенный момент моего приложения мне нужно запустить определенные системные команды (для примера давайте придерживаться перезагрузки, остановки ...). Я создал «базовый» (абстрактно-ммннно-не очень выглядящий) класс «Command» и «CommandManager», который получит строку с командой для запуска, создаст соответствующий экземпляр для указанной команды, поставит ее в очередь и отправит Команды, когда это необходимо (или когда это возможно). Все экземпляры класса «Command» будут перезаписывать метод «execute», который фактически выполняет команду. Если я хочу выполнить «перезагрузку», я бы расширил класс «Command» класса «RebootCommand» и перезаписал это «execute», сделав вызов внешнему приложению «shutdown -r» или «reboot».
Конечная цель - сделать что-то вроде:
CommandManager.execute("reboot")
И система перезагрузится.
Для этого строка " reboot " должна быть зарегистрирована в словаре внутри CommandManager. Этот словарь будет иметь значение « reboot » (строка) в качестве ключа и класс RebootCommand в качестве значения. CommandManager получит строку « reboot », перейдет к его «commandDictionary», создаст экземпляр класса RebootCommand и вызовет его метод execute () (таким образом, перезагрузив систему).
Что-то вроде:
#------------- CommandManager.py -------------
@classmethod
def execute(cls, parameter):
if parameter in cls.validCommands:
tmpCommand = cls.validCommands[parameter]()
tmpCommand.execute()
#---------------------------------------------
Чтобы выполнить регистрацию, должен быть создан объект класса RebootCommand, и для этого я должен импортировать его куда-нибудь. Но я не хочу. Мне не нужно Мне просто нужно создать объект класса RebootCommand, чтобы он выполнял метод __new__
для командного метакласса, в котором происходит регистрация (как подробно описано в ответе на другой вопрос выше).
Есть ли способ сделать это? Я попытался импортировать фактические команды (классы, унаследованные от Command) в __init__.py
, но затем, если я создаю новую команду, мне нужно добавить ее в __init__.py
, и я хотел бы избежать этого ( так что другой программист может создать новую команду, не беспокоясь о том, чтобы забыть добавить класс в __init__.py
)
Вот моя структура каталогов:
commands/
__init__.py
CommandManager.py
Command.py
RebootCommand.py
И вот, содержимое Command и RebootCommand, которые делают регистрацию:
#--------------- Command.py -------------------
def register(newCommand):
if newCommand and newCommand._command:
import CommandManager
CommandManager.CommandManager.registerCommand(newCommand._command, newCommand)
# Fancy registering! https://stackoverflow.com/questions/5189232/how-to-auto-register-a-class-when-its-defined
class CommandMetaClass(type):
def __new__(cls, clsname, bases, attrs):
newCommand = super(cls, CommandMetaClass).__new__(cls, clsname, bases, attrs)
register(newCommand) # here is your register function
return newCommand
class Command(object):
__metaclass__ = CommandMetaClass
_command = None
#-----------------------------------------------------
и ...
#--------------- RebootCommand.py -------------------
class RebootCommand(Command.Command):
_command = "reboot"
#---------------------------------------------------
Процесс регистрации выполняется правильно, если я открываю __init__.py
и пишу:
import RebootCommand
(на этом этапе создается объект класса RebootCommand,
CommandMetaClass.__new__
функция запущена, "перезагрузка" зарегистрирована как класс RebootCommand, и все довольны)
но я бы хотел избежать этого (касаясь __init__.py
), если возможно
Я попытался импортировать с подстановочным знаком * без удачи.
Подводя итог, я хотел бы, чтобы другой программист, который хочет реализовать новую Команду, просто должен создать новый класс, унаследованный от Command, но без добавления его в __init__.py
Я знаю, что ничего нельзя исправить с помощью комментария в файле Command.py, говорящего что-то вроде "любой класс, унаследованный от этого, должен быть добавлен в __init__.py
", но мне любопытно узнать, если я может сделать это более «элегантно».