Python 的 importlib 并检查静态 class 成员
Python's importlib and inspect for static class members
在长 运行 应用程序中,我需要根据 class 模块的路径和 class 名称动态修改静态 class 成员。
例如。我有一个 class pack1.mod1.Person
,根据定义我知道它有一个 age
属性。因此,利用 importlib
和 inspect
我尝试使用模块路径和 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
中,我希望 member
和 Person
是同一件事,但正如示例所示,它们不是。
我遗漏了什么以及如何在 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}`
在长 运行 应用程序中,我需要根据 class 模块的路径和 class 名称动态修改静态 class 成员。
例如。我有一个 class pack1.mod1.Person
,根据定义我知道它有一个 age
属性。因此,利用 importlib
和 inspect
我尝试使用模块路径和 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
中,我希望 member
和 Person
是同一件事,但正如示例所示,它们不是。
我遗漏了什么以及如何在 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}`