简体   繁体   English

导入Python模块时__package__为None

[英]__package__ is None when importing a Python module

I want to import the modules dynamically, by the following way: 我想通过以下方式动态导入模块:

I create a folder named pkg with this structure: 我用这种结构创建了一个名为pkg的文件夹:

pkg
   |__init__.py
   |foo.py

In the head of __init__.py , add this code fragement: __init__.py的头部,添加此代码fragement:

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__;

I found m.__package__ is None in case there is no import statements in foo.py but if I add a simple import statement like this: 我发现如果foo.py中没有import语句, m.__package__None ,但是如果我添加一个这样的简单import语句:

import os

then m.__package__ is "pkg" which is correct package name. 那么m.__package__是“pkg”,这是正确的包名。 why this happens? 为什么会这样?

How to import a module and ensure its correct package attribute? 如何导入模块并确保其正确的包属性?

The __package__ attribute, as you've noticed, isn't set consistently. 正如您所注意到的, __package__属性未设置一致。 (More information at the bottom.) However, you should always be able to get the package name by taking everything before the last period in a module's __name__ attribute. (更多信息在底部。)但是,您应始终能够通过在模块的__name__属性中的最后一个句点之前获取所有内容来获取包名称。 Eg. 例如。 mymod.__name__.rpartition('.')[0] . mymod.__name__.rpartition('.')[0] For your purpose though, it's probably easier just to build the package/module hierarchy as you load the modules. 但是,出于您的目的,在加载模块时构建包/模块层次结构可能更容易。

For example, here's a function that loads all the modules within a package, recursively loading modules within subpackages, etc. (I'm assuming here that you don't mind functions with side-effects..) 例如,这是一个函数,它加载一个包中的所有模块,递归地加载子包中的模块等(我假设你不介意有副作用的函数..)

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)

Sample output: 样本输出:

dummypackage :
    modx
    mody
    pack1 :
        mod1
        pack2 :
            mod2

More information: 更多信息:

The __package__ attribute is used internally by the import system to allow for easy relative imports within a package. __package__属性由导入系统在内部使用,以便在包中轻松进行相对导入。 For details, see PEP 366 . 有关详细信息,请参阅PEP 366 To (presumably) save time when loading modules, the attribute is only set if the loaded module imports another module. 为了(可能)在加载模块时节省时间,仅在加载的模块导入另一个模块时才设置该属性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM