Python 的 importlib 并检查静态 class 成员

Python's importlib and inspect for static class members

在长 运行 应用程序中,我需要根据 class 模块的路径和 class 名称动态修改静态 class 成员。

例如。我有一个 class pack1.mod1.Person,根据定义我知道它有一个 age 属性。因此,利用 importlibinspect 我尝试使用模块路径和 class 名称加载 class 并更新 age 属性。一切似乎都很好,直到我从自然导入的 Person class 中读取 age 属性 并发现它没有更新。

以下是更多详细信息:

.
├── app.py
└── pack1
    ├── __init__.py
    └── mod1.py

mod1.py

class Person:
    age = 42

app.py

import inspect
import os
from importlib import util

from pack1.mod1 import Person

if __name__ == '__main__':
    Person.age = 3
    print(Person.age)  # => 3

    spec = util.spec_from_file_location('pack1.mod1', os.path.join('pack1', 'mod1.py'))
    module = util.module_from_spec(spec)
    spec.loader.exec_module(module)

    members = inspect.getmembers(module)

    for x, member in inspect.getmembers(module, lambda i: inspect.isclass(i) and i.__name__ == Person.__name__):
        print('Person:', Person.age)  # => Person: 3
        print('Person from inspect:', member.age)  # => Person from inspect: 42
        Person.age = 11
        member.age = 66
        print('Person:', Person.age)  # => Person: 11
        print('Person from inspect:', member.age)  # => Person from inspect: 66

app.py 中,我希望 memberPerson 是同一件事,但正如示例所示,它们不是。

我遗漏了什么以及如何在 class 的静态成员上实现这样的更新?

Python 无法知道定期导入的模块和手动模块是“相同的”:使用 util.spec_from_file_location 最多 spec.loader.exec_module 个旁路步骤 Python 的模块注册表并显式创建模块的新实例。
相反,使用解释器的本机操作 (import, ...) 或其编程等效项 (importlib.load_module, ...)

如果module/class知名度高,可以import定期直接考察

import pack1.mod1
pack1.mod1.Person.age = 66

如果模块和class只知道名称,可以从现有模块中查找它们。

import importlib

module_name, qualname, attribute, value = 'pack1.mod1', 'Person', 'age', 66

obj = importlib.import_module(module_name)  # same as `import {module_name}`
for part in qualname.split('.'):
    obj = getattr(obj, part)                # same as `{obj}.{part}

setattr(obj, attribute, value)              # same as `{obj}.{attribute} = {value}`