4

说我有这个结构。

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

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

所以而不是做

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__,但是根据我所读到的,我们应该避免“从包导入 *”

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

4

4 回答 4

4

__init__.py中,您可以:

import a, b, c, d...

然后package在你做之后模块将被放置在命名空间中import package

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

于 2012-06-14T19:05:32.873 回答
2

您提出的建议是非常糟糕的设计实践,因为您导入了所有但不是所需的内容。一般来说,它会减慢程序加载速度——如果不是真的需要,就不要这样做。也不要初始化模块中未使用的变量,因为它浪费时间。

如果使用不当,两种解决方案不符合良好的设计实践。

检查这个答案有人可以用 Python 解释 __all__ 吗?.

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

顺便说一句,这种模式会导致严重的安全漏洞,因为您允许加载任何内容 - 它只需要创建权限即可破坏安全性。

于 2012-06-14T19:18:05.810 回答
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])
于 2012-06-14T19:18:37.107 回答
1

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

import os

for i in os.listdir('package'):
    if i.endswith('.py') and not i.startswith('__'):
        exec('from package import ' + i[:-3])
于 2012-06-14T19:11:38.340 回答