将包中的所有类设置为类属性

时间:2016-07-03 17:12:06

标签: python class python-import

给出以下包结构:

master.py
models/
  __init__.py
  model1.py
  model2.py
  model3.py

其中每个模型* .py文件包含一个或多个类,如何在master.py中创建一个动态导入其中每个类并将其设置为自身属性的类?目前我有以下内容:

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

但这要求我明确说明每个导入的模块和类。我希望这个过程是自动/软编码的,所以如果我以后添加或删除模型,我将不需要更新数据库类。

1 个答案:

答案 0 :(得分:0)

嗯......我不认为这是最好的方式 - 我个人更喜欢手动处理所有导入。但我会假设你有理由并回答你的问题。

首先,您需要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异常,但你可以添加我认为。此外,有人可能会制作一个聪明的文件名并强制执行任意代码。所以......小心点。