I want to import the modules dynamically, by the following way:
I create a folder named pkg with this structure:
pkg
|__init__.py
|foo.py
In the head of __init__.py
, add this code 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 state开发者_JS百科ment like this:
import os
then m.__package__
is "pkg" which is correct package name.
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. (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. Eg. 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. For details, see PEP 366. To (presumably) save time when loading modules, the attribute is only set if the loaded module imports another module.
精彩评论