我想通过以下方式动态导入模块:
我创建了一个名为pkg的文件夹,其结构如下:
pkg
|__init__.py
|foo.py
在__init__.py
的头部,添加此代码片段:
pkgpath = os.path.dirname(pkg.__file__);
for module in pkgutil.iter_modules([pkgpath]):
__import__(module[1], locals(), globals());
m = sys.modules[module[1]];
print m.__package__;
如果foo.py中没有import语句,我发现m.__package__
为None
但是如果我添加一个这样的简单导入语句:
import os
然后m.__package__
是“pkg”,这是正确的包名。
为什么会这样?
如何导入模块并确保其正确的包属性?
答案 0 :(得分:9)
您注意到__package__
属性并未始终如一地设置。 (更多信息在底部。)但是,您应该始终能够通过在模块的__name__
属性中的最后一个句点之前获取所有内容来获取包名称。例如。 mymod.__name__.rpartition('.')[0]
。尽管如此,在加载模块时构建软件包/模块层次结构可能更容易。
例如,这里有一个函数,可以加载包中的所有模块,递归地在子包中加载模块等等(我假设你不介意有副作用的函数) ..)
import sys
import pkgutil
from os.path import dirname
def loadModules(pkg):
pkg._modules = []
pkgname = pkg.__name__
pkgpath = dirname(pkg.__file__)
for m in pkgutil.iter_modules([pkgpath]):
modulename = pkgname+'.'+m[1]
__import__(modulename, locals(), globals())
module = sys.modules[modulename]
module._package = pkg
# module._packageName = pkgname
pkg._modules.append(module)
if dirname(module.__file__) == pkgpath:
module._isPackage = False
else:
module._isPackage = True
loadModules(module)
def modName(mod):
return mod.__name__.rpartition('.')[-1]
def printModules(pkg, indent=0):
print '\t'*indent, modName(pkg), ':'
indent += 1
for m in pkg._modules:
if m._isPackage:
printModules(m, indent)
else:
print '\t'*indent, modName(m)
import dummypackage
loadModules(dummypackage)
printModules(dummypackage)
示例输出:
dummypackage :
modx
mody
pack1 :
mod1
pack2 :
mod2
更多信息:
导入系统在内部使用__package__
属性,以便在包中轻松进行相对导入。有关详细信息,请参阅PEP 366。为了(可能)在加载模块时节省时间,仅在加载的模块导入另一个模块时才设置该属性。