Проблема с использованием super (python 2.5.2)
-
03-07-2019 - |
Вопрос
Я пишу систему плагинов для своей программы, и я не могу пройти мимо одной вещи:
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
Тестовый плагин выглядит следующим образом:
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)
Теперь ipplugin выглядит следующим образом:
class IPlugin(object):
'''
classdocs
'''
name=''
def __init__(self, loader):
self.loader=loader
def activate(self):
pass
Все классы IPlugin работают безупречно сами по себе, но при вызове ThingLoader программа получает исключение:
File "./plugins\TestPlugin.py", line 13, in __init__
super(TestPlugin, self).__init__(loader) NameError:
global name 'super' is not defined
Я огляделся по сторонам и просто не понимаю, что происходит.
Решение
‘супер’ - это встроенное.Если вы не приложили все усилия, чтобы удалить встроенные компоненты, вы никогда не должны видеть “глобальное имя 'super' не определено”.
Я смотрю на твой пользовательская веб-ссылка где есть дамп IntrospectionHelper.Это очень трудно читать без отступов, но, похоже, вы делаете именно это:
built_in_list = ['__builtins__', '__doc__', '__file__', '__name__']
for i in built_in_list:
if i in module.__dict__:
del module.__dict__[i]
Это исходный модуль dict, который вы там меняете, а не информационная копия, которую вы собираетесь вернуть!Удалите этих участников из живого модуля, и вы можете ожидать гораздо большего, чем просто разрыв ‘super’.
Очень трудно уследить за тем, что делает этот модуль, но моя реакция такова, что в нем слишком много магии.Среднестатистической программе на Python никогда не нужно возиться с системой импорта, sys.path и элементами модуля monkey-patching __magic__.Немного магии может стать отличным трюком, но это чрезвычайно хрупкое средство.Сразу после просмотра мне пришло в голову, что код может быть взломан такими вещами, как:
- имя конфликтует с модулями верхнего уровня
- любое использование классов нового стиля
- модули поставляются только в виде скомпилированного байт-кода
- зипимпортер
Из невероятно сложных функций, таких как getClassDefinitions, extractModuleNames и isFromBase, мне кажется, что вам еще предстоит немного узнать об основах работы Python.(Подсказки:getattr, модуль.__name__ и issubclass соответственно.)
В данном случае сейчас это нет самое время окунуться в импортную магию!Это жесткий.Вместо этого делайте все Обычным способом Python.Возможно, потребуется немного больше текста, чтобы указать в нижней части упаковки. mypackage/__init__.py:
from mypackage import fooplugin, barplugin, bazplugin
plugins= [fooplugin.FooPlugin, barplugin.BarPlugin, bazplugin.BazPlugin]
но это будет работать и будет понято везде, не полагаясь на гнездо сложной, хрупкой магии.
Кстати, если вы не планируете какую-то углубленную работу по множественному наследованию (и опять же, сейчас может быть не время для этого), вам, вероятно, даже не нужно использовать super().Обычный метод “IPlugin.__init__(self, ...)” для вызова известного суперкласса - это простая вещь, которую нужно сделать;super() не всегда является “новым, лучшим способом ведения дел” и есть вещи, которые вы должны понимать в этом прежде чем вы начнете заряжаться от его использования.
Другие советы
Если вы не используете версию Python более раннюю, чем 2.2 (довольно маловероятно), super ()
определенно является встроенная функция (доступна в любой области видимости и ничего не импортирует).
Может быть стоит проверить вашу версию Python (просто запустите интерактивное приглашение, набрав python в командной строке).