【问题标题】:__package__ is None when importing a Python module__package__ 在导入 Python 模块时为 None
【发布时间】:2011-05-25 03:45:17
【问题描述】:

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

我用这个结构创建了一个名为 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 中没有导入语句,我发现 m.__package__None 但是如果我添加这样一个简单的导入语句:

import os

然后m.__package__ 是“pkg”,这是正确的包名称。 为什么会这样?

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

【问题讨论】:

  • 很难看到你的目标。至少表明你打算如何调用或导入 pkg。
  • 你为什么要那样做?你到底想解决什么问题?
  • 让我给出我的目标:我需要创建一个函数来加载所有模块一个在运行时提供的包。包可以嵌套——这意味着这个包中有子包。如果所有模块都正确加载,另一个函数将分析任意两个模块之间的关系。例如,如果一个模块中的 package 属性是另一个模块的名称,那么后者就是前者的包。

标签: python module load dynamic


【解决方案1】:

您已经注意到,__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。为了(可能)在加载模块时节省时间,只有在加载的模块导入另一个模块时才设置该属性。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-06
    • 1970-01-01
    • 1970-01-01
    • 2011-08-14
    • 2012-03-07
    • 1970-01-01
    • 2015-05-27
    相关资源
    最近更新 更多