从自定义包导入大量模块

时间:2012-06-14 18:55:54

标签: python import module packages

说我有这个结构。

MyApp
├── main.py
└── package
    ├── __init__.py
    ├── a.py
    ├── b.py
    ├── c.py
    ├── d.py
    ├── e.py
    ├── f.py
    ├── g.py
    ├── h.py
    ├── ...
    └── z.py

main.py我需要使用所有模块,从a.pyz.py

我想知道如何使用一个import语句导入所有这些模块。

所以不要做

from package import a
from package import b
...
from package import z

我可以导入包并准备好所有模块。

我尝试过的事情

import package
a = package.a.A()
# AttributeError: 'module' object has no attribute 'a'

现在我知道我可以在__init__.py中添加一个代码来将所有模块添加到__all__,但是根据我的阅读,我们应该避免'从包导入*'

原因是包可能有越来越多的模块,我想在每次创建模块时向主代码添加一个import语句。理想情况下,我希望能够将模块放入包中并准备好使用。

4 个答案:

答案 0 :(得分:4)

__init__.py中,您可以:

import a, b, c, d...

然后在执行package后,模块将被放置在import package命名空间中。

你真的想在main.py的命名空间中命名ab等,并且不费力地发生这种情况,你无法真正避免from package import *;任何其他隐式导入它们的方法都会同样糟糕,因为它涉及使用未明确导入的名称来污染命名空间。

答案 1 :(得分:2)

你提出的是非常糟糕的设计实践,因为你导入了所有但不是必需的东西。一般来说,IT SLOWS DOWN程序加载 - 如果不是真的需要,就不要这样做。从不浪费时间来初始化模块中未使用的变量。

如果使用不正确,两种解决方案不符合良好的设计惯例。

检查此答案Can someone explain __all__ in Python?

您还可以使用__import__加载模块,os.path.dirname(__file__)列出目录中的所有文件名,并作为模块加载。

BTW这种模式导致了严重的安全漏洞,因为你允许加载任何东西 - 它只需要创建权限来破坏安全性。

答案 2 :(得分:2)

我建议这样做。如果必须,这是我过去使用的方法:

# __init__.py

import os
import re

PACKAGE = 'MyApp.package'
MODULE_RE = r"^.*.py$"

for filename in os.listdir(os.path.dirname(__file__)):
  if not re.match(MODULE_RE, filename) or filename == "__init__.py":
    continue

  imported_module = __import__('%s.%s' % (PACKAGE, filename[:-3]),
                               {}, {},
                               filename[:-3])

答案 3 :(得分:1)

这段代码不是很漂亮,但我认为这是一个很好的解决方法

import os

for i in os.listdir('package'):
    if i.endswith('.py') and not i.startswith('__'):
        exec('from package import ' + i[:-3])