Pull to refresh

Плагины в Python

Reading time4 min
Views16K
Сегодня я расскажу, как построить плагиновую архитектуру в python на include'ах.




Наше приложение будет получать команды и раздавать их плагинам в надежде, что какой-нибудь плагин ее да и обработает

Хитрый план

  • При запуске сканируем папку с плагинами
  • Импортируем все найденные файлы
  • При получении команды отсылаем ее каждому плагину




main.py


Здесь содержится только код «внешней» части примера, и комментировать его, надеюсь, не нужно.

Copy Source | Copy HTML
  1. import plugin
  2.  
  3. plugin.LoadPlugins()
  4.  
  5. s = ''
  6.  
  7. while (s != 'exit'):
  8.     print '>',
  9.     s = raw_input()
  10.     a = s.split(' ')
  11.  
  12.     for p in plugin.Plugins:
  13.         p.OnCommand(a[0], a[1:])
  14.  


Весь код, относящийся к плагинам мы вынемем в plugin.py

plugin.py


Copy Source | Copy HTML
  1. import os
  2. import sys
  3.  
  4. # Экземпляры загруженных плагинов
  5. Plugins = []
  6.  
  7. # Базовый класс плагина
  8. class Plugin(object):
  9.     Name = 'undefined'
  10.  
  11.     # Методы обратной связи
  12.     def OnLoad(self):
  13.         pass
  14.  
  15.     def OnCommand(self, cmd, args):
  16.         pass
  17.  
  18.  
  19. def LoadPlugins():
  20.     ss = os.listdir('plugins') # Получаем список плагинов в /plugins
  21.     sys.path.insert( 0, 'plugins') # Добавляем папку плагинов в $PATH, чтобы __import__ мог их загрузить
  22.  
  23.     for s in ss:
  24.         print 'Found plugin', s
  25.         __import__(os.path.splitext(s)[ 0], None, None, ['']) # Импортируем исходник плагина
  26.  
  27.     for plugin in Plugin.__subclasses__(): # так как Plugin произведен от object, мы используем __subclasses__, чтобы найти все плагины, произведенные от этого класса
  28.         p = plugin() # Создаем экземпляр
  29.         Plugins.append(p)
  30.            p.OnLoad() # Вызываем событие загруки этого плагина
  31.  
  32.     return
  33.  
  34.  


plugins/foo.py — пример плагина


Copy Source | Copy HTML
  1. from plugin import Plugin
  2.  
  3. class HelloPlugin(Plugin): # производим наш плагин от родительского класса
  4.     Name = 'HelloPlugin v 1.0 Extreme Edition'
  5.  
  6.     # замещаем нужные методы
  7.     def OnLoad(self):
  8.         print 'HelloPlugin 1.0 Extreme VIP Edition Loaded!'
  9.  
  10.     def OnCommand(self, cmd, args):
  11.         if (cmd == 'hello' and len(args)> 0):
  12.             print 'It\'s', args[ 0], '!\nJeez, man, nice to meet you!'
  13.             return True
  14.         else:
  15.             return False
  16.  
  17.  


Сейчас уже можно запустить пример:
$ python main.py
Found plugin foo.py
HelloPlugin 1.0 Extreme VIP Edition Loaded!
> hello %username%
It's %username%!
Jeez, man, nice to meet you!
>


plugins/shell.py — плагин посложнее


Сделаем плагин, который будет транслировать команды шеллу и возвращать вывод:

Copy Source | Copy HTML
  1. from plugin import Plugin
  2. import commands
  3.  
  4. class ShellPlugin(Plugin):
  5.     Name = 'Shell plugin'
  6.  
  7.     def OnLoad(self):
  8.         print 'Shell plugin loaded.'
  9.  
  10.     def OnCommand(self, cmd, args):
  11.         if (cmd == 'run'):
  12.             print commands.getoutput (" ".join(args))
  13.             return True
  14.         else:
  15.             return False
  16.  


$ python main.py
Found plugin shell.py
Found plugin foo.py
Shell plugin loaded.
HelloPlugin 1.0 Extreme VIP Edition Loaded!
> run uname -r
2.6.31-14-generic
> exit


Вот и все!
Скачать исходный код
Tags:
Hubs:
Total votes 57: ↑48 and ↓9+39
Comments45

Articles