代码之家  ›  专栏  ›  技术社区  ›  Noldorin

在目录中列出类(Python)

  •  4
  • Noldorin  · 技术社区  · 14 年前

    我正在开发一个python2.6包,在这个包中,我想获取某个目录(包中)中所有类的列表,以便对类对象执行内省。

    具体来说,如果包含当前正在执行的模块的目录有一个名为“foobar”的子目录,并且“foobar”包含指定 class Foo(MyBase) , class Bar(MyBase) ,和 class Bar2 MyBase ,即。 Foo Bar ,但不是 Bar2 .

    我不确定这个任务是否真的需要处理文件系统,或者子目录中的模块是否自动加载,只需要通过内省列出。有什么想法吗?示例代码非常受欢迎,因为我对Python非常陌生,尤其是内省。

    5 回复  |  直到 14 年前
        1
  •  8
  •   Community taleinat    5 年前

    __import__ 内置功能:

    import os
    from glob import glob
    for file in glob(os.path.join(os.path.dirname(os.path.abspath(__file__))), "*.py"):
        name = os.path.splitext(os.path.basename(file))[0]
        # add package prefix to name, if required
        module = __import__(name)
        for member in dir(module):
            # do something with the member named ``member``
    
        2
  •  6
  •   krakover    10 年前

    import glob
    import importlib
    import inspect
    import os
    
    current_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)))
    current_module_name = os.path.splitext(os.path.basename(current_dir))[0]
    for file in glob.glob(current_dir + "/*.py"):
         name = os.path.splitext(os.path.basename(file))[0]
    
         # Ignore __ files
         if name.startswith("__"):
             continue
         module = importlib.import_module("." + name,package=current_module_name)
    
         for member in dir(module):
             handler_class = getattr(module, member)
    
             if handler_class and inspect.isclass(handler_class):
                 print member
    

    希望有帮助。。

        3
  •  3
  •   culebrón    14 年前

    选项2:使目录成为一个包(创建一个空的\uuu init \uuuu.py文件),导入它并递归遍历它的成员:

    import mymodule
    def itermodule(mod):
        for member in dir(mymod):
            ...
    
    itermodule(mymodule)
    
        4
  •  3
  •   Jossef Harush Kadouri    8 年前

    我自己处理的,这是我的版本(forked@krakover snippet):

      • 过滤出抽象类
      • 筛选出不继承基类的类
      • 为每个迭代类创建一个新实例(如果您不觉得它有用,请更改它)

    import importlib
    import inspect
    import os
    import glob
    
    
    def import_plugins(plugins_package_directory_path, base_class=None, create_instance=True, filter_abstract=True):
    
        plugins_package_name = os.path.basename(plugins_package_directory_path)
    
        # -----------------------------
        # Iterate all python files within that directory
        plugin_file_paths = glob.glob(os.path.join(plugins_package_directory_path, "*.py"))
        for plugin_file_path in plugin_file_paths:
            plugin_file_name = os.path.basename(plugin_file_path)
    
            module_name = os.path.splitext(plugin_file_name)[0]
    
            if module_name.startswith("__"):
                continue
    
            # -----------------------------
            # Import python file
    
            module = importlib.import_module("." + module_name, package=plugins_package_name)
    
            # -----------------------------
            # Iterate items inside imported python file
    
            for item in dir(module):
                value = getattr(module, item)
                if not value:
                    continue
    
                if not inspect.isclass(value):
                    continue
    
                if filter_abstract and inspect.isabstract(value):
                    continue
    
                if base_class is not None:
                    if type(value) != type(base_class):
                        continue
    
                # -----------------------------
                # Instantiate / return type (depends on create_instance)
    
                yield value() if create_instance else value
    

    用法:

    SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
    plugins_directory_path = os.path.join(SCRIPT_DIR, 'plugins')
    plugins = import_plugins(plugins_directory_path, base_class=BasePlugin)
    
    for plugin in plugins:
        plugin.foo()
    
    • plugins 包含 BasePlugin
        5
  •  -1
  •   Mark    11 年前

    在有白鹭的平台上:

    from subprocess import Popen, PIPE
    from re import search
    
    def get_classes(directory):
        job = Popen(['egrep', '-ir', '--include=*.py', 'class ', str(directory), ], stdout=PIPE)
        fileout, fileerr = job.communicate()
        if fileerr:
            raise Exception(fileerr)
        while directory[-1] == '/':
            directory = directory[:-1]
        found = []
        for line in fileout.split('\n'):
            match = search('^([^:]+).py:\s*class\s*(\S+)\s*\((\S+)\):', line)
            if match:
                pypath = match.group(1).replace(directory, '').replace('/', '.')[1:]
                cls = match.group(2)
                parents = filter(lambda x: x.strip, match.group(3).split())
                found.append((pypath, cls, parents, ))
        return found
    

    get_classes('.') ,egrep返回类似于:

    ./helpers/action.py:class Action(object):
    ./helpers/get_classes.py:    job = Popen(['egrep', '-ir', '--include=*.py', 'class ', str(directory), ], stdout=PIPE) # this is the get_classes script; not a valid result
    ./helpers/options.py:class Option(object):
    

    [('helpers.action', 'Action', ['object']), ('helpers.options', 'Option', ['object'])]
    

    如果你只想知道路,那就是 [item[0] for item in get_classes('.')] .