Problema nell'uso di super (python 2.5.2)
-
03-07-2019 - |
Domanda
Sto scrivendo un sistema di plugin per il mio programma e non riesco a superare una cosa:
class ThingLoader(object):
'''
Loader class
'''
def loadPlugins(self):
'''
Get all the plugins from plugins folder
'''
from diones.thingpad.plugin.IntrospectionHelper import loadClasses
classList=loadClasses('./plugins', IPlugin)#Gets a list of
#plugin classes
self.plugins={}#Dictionary that should be filled with
#touples of objects and theirs states, activated, deactivated.
classList[0](self)#Runs nicelly
foo = classList[1]
print foo#prints <class 'TestPlugin.TestPlugin'>
foo(self)#Raise an exception
Il plug-in di test è simile al seguente:
import diones.thingpad.plugin.IPlugin as plugin
class TestPlugin(plugin.IPlugin):
'''
classdocs
'''
def __init__(self, loader):
self.name='Test Plugin'
super(TestPlugin, self).__init__(loader)
Ora IPlugin è simile al seguente:
class IPlugin(object):
'''
classdocs
'''
name=''
def __init__(self, loader):
self.loader=loader
def activate(self):
pass
Tutte le classi IPlugin funzionano perfettamente da sole, ma quando vengono chiamate da ThingLoader il programma ottiene un'eccezione:
File "./plugins\TestPlugin.py", line 13, in __init__
super(TestPlugin, self).__init__(loader) NameError:
global name 'super' is not defined
Mi sono guardato intorno e semplicemente non so cosa stia succedendo.
Soluzione
"super" è incorporato. A meno che tu non abbia fatto di tutto per eliminare i builtin, non dovresti mai vedere "il nome globale 'super' non è definito".
Sto guardando il tuo link web dell'utente dove c'è un dump di IntrospectionHelper. È molto difficile da leggere senza il rientro, ma sembra che tu stia facendo esattamente questo:
built_in_list = ['__builtins__', '__doc__', '__file__', '__name__']
for i in built_in_list:
if i in module.__dict__:
del module.__dict__[i]
Questo è il modulo originale che stai cambiando lì, non una copia informativa che stai per restituire! Elimina questi membri da un modulo live e puoi aspettarti molto di più di un "super" da interrompere.
È molto difficile tenere traccia di ciò che quel modulo sta facendo, ma la mia reazione è che c'è troppa magia in esso. Il programma Python medio non dovrebbe mai aver bisogno di scherzare con i membri del modulo __magic__ del sistema di importazione, sys.path e patching delle scimmie. Un po 'di magia può essere un trucco, ma questo è estremamente fragile. Appena fuori dalla mia testa dalla navigazione, il codice potrebbe essere rotto da cose come:
- scontro di nomi con moduli di livello superiore
- qualsiasi uso di classi di nuovo stile
- moduli forniti solo come bytecode compilato
- zipimporter
Dalle funzioni incredibilmente complete come getClassDefinitions, extractModuleNames e isFromBase, mi sembra che tu abbia ancora un po 'di cose da imparare su come funziona Python. (Indizi: getattr, module .__ name__ e issubclass, rispettivamente.)
In questo caso ora non è il momento di immergerti nella magia delle importazioni! È difficile . Invece, fai le cose in modo normale. Potrebbe essere un po 'più di battitura da dire in fondo al mypackage di un pacchetto / __ init__.py:
from mypackage import fooplugin, barplugin, bazplugin
plugins= [fooplugin.FooPlugin, barplugin.BarPlugin, bazplugin.BazPlugin]
ma funzionerà e sarà compreso ovunque senza fare affidamento su un nido di magia complessa e fragile.
Per inciso, a meno che tu non stia pianificando un lavoro approfondito sull'ereditarietà multipla (e di nuovo, ora potrebbe non essere il momento per quello), probabilmente non hai nemmeno bisogno di usare super (). Il solito metodo "IPlugin .__ init __ (self, ...)" per chiamare una superclasse conosciuta è la cosa più semplice da fare; super () non è sempre "il modo più nuovo e migliore di fare le cose" e ci sono cose che dovresti capire al riguardo prima di iniziare a caricarlo per usarlo.
Altri suggerimenti
A meno che tu non stia eseguendo una versione di Python precedente alla 2.2 (abbastanza improbabile), super ()
è sicuramente un funzione integrata (disponibile in tutti gli ambiti e senza importare nulla).
Potrebbe valere la pena di verificare la versione di Python (basta avviare il prompt interattivo digitando python dalla riga di comando).