Атрибут __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 . Чтобы (предположительно) сэкономить время при загрузке модулей, атрибут устанавливается только в том случае, если загруженный модуль импортирует другой модуль.