说我有这个结构。
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.py
到z.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语句。理想情况下,我希望能够将模块放入包中并准备好使用。
答案 0 :(得分:4)
在__init__.py
中,您可以:
import a, b, c, d...
然后在执行package
后,模块将被放置在import package
命名空间中。
你真的想在main.py的命名空间中命名a
,b
等,并且不费力地发生这种情况,你无法真正避免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])