Je voudrais enregistrer une classe (pas une instance) lors de sa création... mais sans l'importer.
En gros, je veux faire ce qui est décrit ici :
Comment enregistrer automatiquement une classe lorsqu'elle est définie ?
... mais sans avoir à importer la classe enregistrée nulle part.
Voici le problème : À un certain moment de mon application, j'ai besoin d'exécuter certaines commandes système (restons-en à reboot, halt... pour l'exemple). J'ai créé une classe "de base" (abstraite-mmnnno-ne ressemblant pas vraiment à ça) "Command" et un "CommandManager" qui recevra une chaîne de caractères avec la commande à exécuter, créera l'instance appropriée pour cette commande, la mettra en file d'attente et distribuera les commandes quand cela sera nécessaire (ou quand il le pourra). Toutes les instances de la classe "Command" écraseront une méthode "execute" qui exécute réellement la commande. Si je veux "redémarrer", j'étendrai la classe "Command" à une classe "RebootCommand", et j'écraserai la méthode "execute" qui appelle l'application externe "shutdown -r" ou "reboot".
Le but final est d'être capable de faire quelque chose comme :
CommandManager.execute("reboot")
Et le système va redémarrer.
Pour ce faire, le " redémarrer "doit être enregistrée dans un dictionnaire à l'intérieur du CommandManager. Ce dictionnaire aura " redémarrer "(chaîne de caractères) comme clé et la classe Commande de redémarrage comme valeur. Le CommandManager recevra la chaîne " redémarrer La commande "RebootCommand" va aller dans son "commandDictionary", créer une instance de la classe RebootCommand et appeler sa méthode execute() (ce qui permet de redémarrer le système).
Quelque chose comme :
#------------- CommandManager.py -------------
@classmethod
def execute(cls, parameter):
if parameter in cls.validCommands:
tmpCommand = cls.validCommands[parameter]()
tmpCommand.execute()
#---------------------------------------------
Pour effectuer l'enregistrement, l'objet de classe RebootCommand doit être créé, et pour ce faire, je dois l'importer quelque part. Mais je ne veux pas le faire. Je n'en ai pas besoin. J'ai juste besoin que l'objet de classe RebootCommand soit créé, afin qu'il exécute la commande __new__
pour la MetaClass Command, où l'enregistrement a lieu (comme indiqué dans la réponse à l'autre question ci-dessus).
Y a-t-il un moyen de le faire ? J'ai essayé d'importer les commandes réelles (les classes qui héritent de Command) dans le répertoire de l'utilisateur. __init__.py
mais ensuite, si je crée une nouvelle commande, je dois l'ajouter à la liste des commandes. __init__.py
et j'aimerais éviter cela (afin qu'un autre programmeur puisse créer une nouvelle commande sans se soucier d'oublier d'ajouter la classe à la classe __init__.py
)
Voici la structure de mon répertoire :
commands/
__init__.py
CommandManager.py
Command.py
RebootCommand.py
Et ici, les contenus de Command et RebootCommand qui font l'enregistrement :
#--------------- 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
#-----------------------------------------------------
et...
#--------------- RebootCommand.py -------------------
class RebootCommand(Command.Command):
_command = "reboot"
#---------------------------------------------------
Le processus d'enregistrement est correctement exécuté si j'ouvre __init__.py
et j'écris :
import RebootCommand
(à ce stade, l'objet de classe RebootCommand est créé,
CommandMetaClass.__new__
est exécutée, "reboot" est enregistré comme la classe RebootCommand, et tout le monde est content)
mais j'aimerais éviter d'avoir à le faire (en touchant __init__.py
), si possible
J'ai essayé d'importer avec le caractère générique * sans succès.
Pour résumer, j'aimerais qu'un autre programmeur qui souhaite implémenter une nouvelle commande, n'ait qu'à créer une nouvelle classe héritant de Command, mais sans avoir à l'ajouter à la liste des classes. __init__.py
Je sais qu'il n'y a rien qui ne puisse être corrigé avec un commentaire dans le fichier Command.py, disant quelque chose comme "toute classe héritant de celle-ci doit être ajoutée dans le fichier __init__.py
"mais je suis curieux de savoir si je peux le faire d'une manière plus "élégante".