导入Python模块时__package__为None

时间:2010-12-14 08:56:18

标签: python module load dynamic

我想通过以下方式动态导入模块:

我创建了一个名为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”,这是正确的包名。 为什么会这样?

如何导入模块并确保其正确的包属性?

1 个答案:

答案 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。为了(可能)在加载模块时节省时间,仅在加载的模块导入另一个模块时才设置该属性。