在Python中,如何获得特定文件中定义的类列表



如果文件myfile.py包含:

class A(object):
  # Some implementation
class B (object):
  # Some implementation

我如何定义一种方法,以便给定myfile.py,它返回[a,b]?

在这里,A和B的返回值可以是类的名称或类的类型。

(i.e. type(A) = type(str) or type(A) = type(type))

您可以同时获得:

import importlib, inspect
for name, cls in inspect.getmembers(importlib.import_module("myfile"), inspect.isclass):

您可能还想检查:

if cls.__module__ == 'myfile'

以防其他人。这是我使用的最终解决方案。此方法返回特定软件包中定义的所有类。

我将X的所有子类放在特定文件夹(软件包)中,然后使用此方法,即使尚未导入X的所有子类,我也可以加载X的所有子类。(如果尚未导入它们,则无法通过__all__访问它们;否则情况会容易得多)。

import importlib, os, inspect
def get_modules_in_package(package_name: str):
    files = os.listdir(package_name)
    for file in files:
        if file not in ['__init__.py', '__pycache__']:
            if file[-3:] != '.py':
                continue
            file_name = file[:-3]
            module_name = package_name + '.' + file_name
            for name, cls in inspect.getmembers(importlib.import_module(module_name), inspect.isclass):
                if cls.__module__ == module_name:
                    yield cls

它有点漫长,但是您首先需要加载文件作为模块,然后检查其方法以查看哪个类别:

import inspect
import importlib.util
# Load the module from file
spec = importlib.util.spec_from_file_location("foo", "foo.py")
foo = importlib.util.module_from_spec(spec)
spec.loader.exec_module(foo)
# Return a list of all attributes of foo which are classes
[x for x in dir(foo) if inspect.isclass(getattr(foo, x))]

仅在上面的答案上构建。

如果您需要在模块(文件)中定义的类列表,即不仅是模块名称空间中存在的类,并且需要该模块中的列表,即使用反射,然后以下将在__name__ == __main____name__ == <module>案例下工作。

import sys, inspect
# You can pass a lambda function as the predicate for getmembers()
[name, cls in inspect.getmembers(sys.modules[__name__], lambda x: inspect.isclass(x) and (x.__module__ == __name__))]

在我非常具体的用例中,将类注册到呼叫框架中,我使用如下:

def register():    
    myLogger.info(f'Registering classes defined in module {__name__}')
    for name, cls in inspect.getmembers(sys.modules[__name__], lambda x: inspect.isclass(x) and (x.__module__ == __name__)):
        myLogger.debug(f'Registering class {cls} with name {name}')
        <framework>.register_class(cls)

如果导入文件会引发错误或不需要的话,可以使用以下内容:

import pyclbr
[k for k, v in pyclbr.readmodule('myfile.py').items() if isinstance(v, pyclbr.Class)]

相关内容

  • 没有找到相关文章

最新更新