2009-05-26 23 views
12

Podczas gdy w Pythonie dość banalne jest importowanie modułu "dziecko" do innego modułu i wyświetlanie jego atrybutów, staje się nieco trudniejsze, gdy chcemy zaimportować wszystkie moduły potomne.Jak znaleźć wszystkie moduły potomne w Pythonie?

Buduję bibliotekę narzędzi do istniejącej aplikacji 3D. Każde narzędzie ma swój własny element menu i podmenu. Chciałbym, aby narzędzie było odpowiedzialne za tworzenie własnych menu, ponieważ wiele z nich zmienia się w zależności od kontekstu i szablonów. Chciałbym, żeby mój moduł bazowy mógł znaleźć wszystkie moduły potomne i sprawdzić funkcję create_menu() i wywołać ją, jeśli ją znajdzie.

Jaki jest najprostszy sposób na odkrycie wszystkich modułów potomnych?

+0

Czy to jest powiązane? [('pkg_resources' z pakietu setuptools)] (http://jeetworks.org/node/49) –

+1

Użyj [pkgutil.walk_packages] (http://docs.python.org/library/pkgutil.html#pkgutil. walk_packages). – Dag

+1

moduły nie są paczkami –

Odpowiedz

0

użyciu dir() i imp module

+0

Imp wygląda dokładnie jak ten moduł, którego potrzebuję! Dzięki. – Soviut

+11

To dość krótka odpowiedź, nie rozumiem, dlaczego została przyjęta. Dokumentacja dir() zakłada, że ​​obiekt ma już atrybuty. Czy mógłbyś rozwinąć i powiedzieć, * jak * należy użyć polecenia dir() do znalezienia modułów jeszcze nie zaimportowanych? – bignose

+3

Nope: '$ mkdir foo $ touch foo/__ init__.py $ touch foo/bar.py $ python Python 2.7.1+ (r271: 86.832, 11 kwietnia 2011, 18:05:24) [GCC 4.5.2] na linux2 Aby uzyskać więcej informacji, wpisz "help", "copyright", "credits" lub "license". >>> import bla >>> bla >>> dir (bla) [ '__builtins__', '__doc__', '__file__', „__name__ ',' __package__ ',' __path__ '] >>> z paska importu foo >>> pasek ' –

1

Kiedy byłem miły i programowania dopiero zaczynają w Pythonie Pisałem to dla mojego modułowym bot IRC:


    # Load plugins 

    _plugins = [] 

    def ifName(name): 
     try: 
      return re.match('([^_.].+)\.[^.]+', a).group(1) 
     except: 
      return None 

    def isValidPlugin(obj): 
     from common.base import PluginBase 
     try: 
      if obj.__base__ == PluginBase: 
       return True 
      else: 
       return False 
     except: 
      return False 

    plugin_names = set(ifilter(lambda a: a!=None, [ifName(a) for a in os.listdir(os.path.join(os.getcwd(), 'plugins'))])) 
    for plugin_name in plugin_names: 
     try: 
      plugin = __import__('plugins.'+plugin_name, fromlist=['plugins']) 
      valid_plugins = filter(lambda a: isValidPlugin(a), [plugin.__getattribute__(a) for a in dir(plugin)]) 
      _plugins.extend(valid_plugins) 
     except Exception, e: 
      logger.exception('Error loading plugin %s', plugin_name) 

    # Run plugins 

    _plugins = [klass() for klass in _plugins] 

To nie jest bezpieczne lub „prawo” sposób, ale może jednak będziemy przydatni. To jest stary kod very, więc proszę mnie nie bić.

+0

Tak, powinieneś używać modułu imp, takiego jak dfa. – deno

-1

Można spróbować glob bing katalogu:

import os 
import glob 

modules = glob.glob(os.path.join('/some/path/to/modules', '*.py')) 

Następnie można spróbować ich importowania:

checked_modules 
for module in modules: 
    try: 
     __import__(module, globals(), locals()) # returns module object 
    except ImportError: 
     pass 
    else: 
     checked_modules.append(module) 
3

Myślę, że najlepszym sposobem, aby robić takie rzeczy pluginu korzysta entry_points oraz API for querying them.

+0

To powinna być zaakceptowana odpowiedź. Rejestrowanie modułów za pomocą punktów wejścia jest znacznie bardziej przejrzyste, przemyślane i podejście Pythoniczne, gdy chcesz je wykryć w czasie wykonywania, i nie powoduje skutków ubocznych spowodowanych zaimportowaniem ich wszystkich w taki sposób, jak robi to 'pkgutil.walk_packages' . –

1

Rozwiązanie powyżej przechodzące przez system plików do znajdowania submodułów jest w porządku, o ile zaimplementujesz każdą wtyczkę jako moduł oparty na systemie plików.

Bardziej elastycznym sposobem jest jawna lista wtyczek w głównym module i każda wtyczka (niezależnie czy jest to moduł utworzony przez plik, dynamicznie, czy nawet wystąpienie klasy), dodając się bezpośrednio do tej listy. Może poprzez funkcję registerPlugin.

Pamiętaj: "wyraźna jest lepsza niż niejawna" jest częścią zenu Pythona.

+0

aby to działało, musisz mieć sposób na to, aby moduły wtyczek były importowane po uruchomieniu aplikacji, w przeciwnym razie nie będą miały możliwości zarejestrowania się. to problem z kurczakiem i jajkiem. bez modułów przesuwania/automatycznego importowania kończy się ręczne importowanie wszystkich modułów w module głównym, co neguje potrzebę funkcji rejestracji, ale łamie zasadę, że główny nie powinien wiedzieć o konkretnych wtyczkach – Anentropic

Powiązane problemy