9

如果文件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))

4

4 回答 4

16

你可以同时获得:

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

您可能还需要检查:

if cls.__module__ == 'myfile'
于 2019-03-08T16:40:06.537 回答
5

以防它帮助别人。这是我使用的最终解决方案。此方法返回特定包中定义的所有类。

我将 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
于 2019-03-08T18:13:52.363 回答
2

这有点冗长,但您首先需要将文件作为模块加载,然后检查其方法以查看哪些是类:

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))]
于 2019-03-08T16:39:21.123 回答
0

只是建立在上面的答案。

如果您需要模块(文件)中定义的类的列表,即不仅仅是模块命名空间中存在的那些,并且您想要该模块中的列表,即使用反射,那么下面将在这两种情况__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)
于 2021-12-30T08:29:09.547 回答