Edit: ecco una soluzione riveduta. Mi sono reso conto che stavo commettendo un errore durante il test del mio precedente, e non funziona come vorresti. Così qui è una soluzione più completa:
import os
from imp import find_module
from types import ModuleType, ClassType
def iter_plugins(package):
"""Receives package (as a string) and, for all of its contained modules,
generates all classes that are subclasses of PluginBaseClass."""
# Despite the function name, "find_module" will find the package
# (the "filename" part of the return value will be None, in this case)
filename, path, description = find_module(package)
# dir(some_package) will not list the modules within the package,
# so we explicitly look for files. If you need to recursively descend
# a directory tree, you can adapt this to use os.walk instead of os.listdir
modules = sorted(set(i.partition('.')[0]
for i in os.listdir(path)
if i.endswith(('.py', '.pyc', '.pyo'))
and not i.startswith('__init__.py')))
pkg = __import__(package, fromlist=modules)
for m in modules:
module = getattr(pkg, m)
if type(module) == ModuleType:
for c in dir(module):
klass = getattr(module, c)
if (type(klass) == ClassType and
klass is not PluginBaseClass and
issubclass(klass, PluginBaseClass)):
yield klass
mia soluzione precedente era:
si potrebbe provare qualcosa di simile:
from types import ModuleType
import Plugins
classes = []
for item in dir(Plugins):
module = getattr(Plugins, item)
# Get all (and only) modules in Plugins
if type(module) == ModuleType:
for c in dir(module):
klass = getattr(module, c)
if isinstance(klass, PluginBaseClass):
classes.append(klass)
In realtà, ancora meglio, se volete un po modularità:
from types import ModuleType
def iter_plugins(package):
# This assumes "package" is a package name.
# If it's the package itself, you can remove this __import__
pkg = __import__(package)
for item in dir(pkg):
module = getattr(pkg, item)
if type(module) == ModuleType:
for c in dir(module):
klass = getattr(module, c)
if issubclass(klass, PluginBaseClass):
yield klass
Puoi richiedere che usano un nome magico per la loro classe? – nmichaels
Perdonami (sono relativamente nuovo a Python), ma cos'è un nome di classe magico? Qualcosa come "__Plugin1__'? –
Penso che intendesse una specie di convenzione di denominazione (diciamo che tutti i plugin sono in file come "plugin_something".py "," plugin_somethingelse.py "), in modo che tu possa filtrare per nome invece di scorrere tutti i moduli e tutte le classi. Personalmente, penso che questo potrebbe essere utile per i moduli (come sono, o potrebbero essere, i nomi dei file), ma ereditare da una classe base è un indicatore abbastanza buono (se non migliore) – rbp