将包内的所有 classes 设置为 class 属性
Set all classes within package as class attributes
给定以下包结构:
master.py
models/
__init__.py
model1.py
model2.py
model3.py
每个 model*.py 文件包含一个或多个 classes,我如何在 master.py 中创建一个动态导入其中每个 class 的 class es并将其设置为自身的属性?目前我有以下内容:
class DB:
def __init__(self):
from models.model1 import foo, bar
from models.model2 import foo2
from models.model3 import bar2
self.foo = foo
self.bar = bar
self.foo2 = foo2
self.bar2 = bar2
但这需要我明确说明每个导入的模块和 class。我希望这个过程是 automatic/soft-coded,这样如果我以后添加或删除模型,我就不需要更新数据库 class。
嗯...我不认为这是执行此操作的最佳方法 — 我个人更喜欢手动处理所有导入。但我假设你有你的理由并回答你的问题。
首先,您需要 models
成为一个模块,因此在继续之前添加一个文件 models/__init__.py
。
import inspect
import os
import sys
class DB(object):
def __init__(self):
# Get current file (`master.py`)'s directory and the `models` directory.
selfdir = os.path.dirname(os.path.abspath(__file__))
models_dir = os.path.join(selfdir, 'models')
# Get all files in `models` that are Python files.
models_files = [file for file in os.listdir(models_dir) if os.path.isfile(os.path.join(models_dir, file)) and file.endswith('.py')]
model_names = [model[:-3] for model in models_files]
for model_name in model_names:
# Exploit Python's ability to execute arbitrary code.
module_name = 'models.{name}'.format(name=model_name)
exec("import {module}".format(module=module_name))
module = sys.modules[module_name]
classes = inspect.getmembers(module, inspect.isclass)
for module_class in classes:
setattr(self, module_class[0], module_class[1])
我测试了它(在 2.7.11 中)并且效果很好,所以如果有什么不适合您,请告诉我。这里有一些假设,你只需要在你的代码库中保证反对,可能通过文档。我没有处理我可能应该用 models
目录处理的 IO 异常,但我认为你可以添加它。此外,有人可能会设计一个巧妙的文件名并强制执行任意代码。所以……小心点。
给定以下包结构:
master.py
models/
__init__.py
model1.py
model2.py
model3.py
每个 model*.py 文件包含一个或多个 classes,我如何在 master.py 中创建一个动态导入其中每个 class 的 class es并将其设置为自身的属性?目前我有以下内容:
class DB:
def __init__(self):
from models.model1 import foo, bar
from models.model2 import foo2
from models.model3 import bar2
self.foo = foo
self.bar = bar
self.foo2 = foo2
self.bar2 = bar2
但这需要我明确说明每个导入的模块和 class。我希望这个过程是 automatic/soft-coded,这样如果我以后添加或删除模型,我就不需要更新数据库 class。
嗯...我不认为这是执行此操作的最佳方法 — 我个人更喜欢手动处理所有导入。但我假设你有你的理由并回答你的问题。
首先,您需要 models
成为一个模块,因此在继续之前添加一个文件 models/__init__.py
。
import inspect
import os
import sys
class DB(object):
def __init__(self):
# Get current file (`master.py`)'s directory and the `models` directory.
selfdir = os.path.dirname(os.path.abspath(__file__))
models_dir = os.path.join(selfdir, 'models')
# Get all files in `models` that are Python files.
models_files = [file for file in os.listdir(models_dir) if os.path.isfile(os.path.join(models_dir, file)) and file.endswith('.py')]
model_names = [model[:-3] for model in models_files]
for model_name in model_names:
# Exploit Python's ability to execute arbitrary code.
module_name = 'models.{name}'.format(name=model_name)
exec("import {module}".format(module=module_name))
module = sys.modules[module_name]
classes = inspect.getmembers(module, inspect.isclass)
for module_class in classes:
setattr(self, module_class[0], module_class[1])
我测试了它(在 2.7.11 中)并且效果很好,所以如果有什么不适合您,请告诉我。这里有一些假设,你只需要在你的代码库中保证反对,可能通过文档。我没有处理我可能应该用 models
目录处理的 IO 异常,但我认为你可以添加它。此外,有人可能会设计一个巧妙的文件名并强制执行任意代码。所以……小心点。