2010-12-14 5 views
5

Я хочу, чтобы импортировать модули динамически, следующим образом:__package__ не None при импорте модуля Python

создать папку с именем упак с этой структурой:

pkg 
    |__init__.py 
    |foo.py 

В голове __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__; 

m.__package__ Я нашел это None в случае нет импорта заявления в foo.py , но если добавить простой оператор импорта, как это:

import os 

m.__package__ то есть «PKG», который является правильным именем пакета. Почему это происходит?

Как импортировать модуль и обеспечить его правильный атрибут пакета?

+0

Трудно видеть вашу цель. По крайней мере, покажите, как вы собираетесь называть или импортировать pkg. –

+0

Зачем вы хотите это сделать? Что вы на самом деле пытаетесь решить? –

+0

Позвольте мне дать свою цель: мне нужно создать функцию для загрузки всех модулей пакета, который предоставляется во время выполнения. Пакет может быть вложенным, что означает, что в этом пакете есть дополнительный пакет. Если все модули правильно загружены, другая функция проанализирует взаимосвязь между любыми двумя модулями. Например, если атрибут __package__ в одном модуле является именем другого модуля, то последний является пакетом первого. – user541676

ответ

7

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

Смежные вопросы