2009-08-27 3 views
1

Извините за общим названием будет изменить его, как только я понимаю, источник моей проблемы я иметь следующую структуру:Проблема с питоном и __import__

foo/ 
foo/__init__.py 
foo/bar/ 
foo/bar/__init__.py 
foo/bar/some_module.py 

Когда я пытаюсь импортировать some_module делая так:

from foo.bar import some_module 

это работает как очарование. Но это не хорошо для меня, так как я знаю только имя модуля для импорта во время выполнения. поэтому, если я попробую:

from foo.bar import * 
mod=__import__('some_module') 

Я получаю сообщение об ошибке. Я делаю что-то неправильно? Есть лучший способ сделать это? и почему это происходит?

Почему? Я не совсем уверен, что полностью понимаю концепцию пакетов python. Я думал, что они были эквивалентны пакетов Java и, таким образом,

+3

Что говорит об ошибке? – ewall

+2

Ваш 'some_module' уже импортирован! – SilentGhost

ответ

7

Я считаю, что правильный способ сделать это:

mod = __import__('foo.bar', fromlist = ['some_module']) 

Таким образом, даже «foo.bar» часть может быть изменен во время выполнения. В результате some_module будет доступен как mod.some_module; использовать GetAttr, если вы хотите его в отдельную переменную:

the_module = getattr(mod, 'some_module') 
0

Из docs:

Direct use of __import__() is rare, except in cases where you want to import a module whose name is only known at runtime.

Однако пунктирная обозначение должно работать:

mod = __import__('foo.bar.some_module') 
1
from foo.bar import * 

плохой поскольку он импортирует some_module в глобальную сферу.

Вы должны быть в состоянии получить доступ к модулю через:

import foo.bar 
mod = getattr(foo.bar, 'some_module') 

Это может быть легко продемонстрировано, что этот подход работает:

>>> import os.path 
>>> getattr(os.path, 'basename') 
<function basename at 0x00BBA468> 
>>> getattr(os.path, 'basename\n') 
Traceback (most recent call last): 
    File "<pyshell#31>", line 1, in <module> 
    getattr(os.path, 'basename\n') 
AttributeError: 'module' object has no attribute 'basename 
' 

P.S. Если вы все еще заинтересованы в использовании своего оператора импорта. Вам нужен eval:

from foo.bar import * 
eval('some_module') 

Для уточнения: не только это плохая практика, чтобы использовать * -import это даже хуже в сочетании с eval. Так что просто используйте getattr, он разработан именно для таких ситуаций, как ваш.

+0

-1 для рекомендации eval(). Всегда используйте globals() ['some_module'] вместо этого, если все, что вам нужно, - это посмотреть значение из глобальной области. –

+0

Хорошо, +1 еще раз для уточнения. getattr() - правильный ответ здесь. Если вам нужно использовать __import __(), см. Ответ kurczak. –

+0

Ух, теперь я получаю «Голосовать слишком стары, чтобы меняться, если этот ответ не отредактирован».Мои извинения - я видел eval() в блоке кода и автоматически щелкал -1. –

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