2009-06-29 11 views
15

Mam folder wiadomości (pakiet) z plikiem __init__.py i innym modułem messages_en.py w środku. W __init__.py gdybym import messages_en to działa, ale __import__ nie powiedzie się z "ImportError: nie moduł o nazwie messages_en"Jak mogę zaimportować pakiet za pomocą __import __(), gdy nazwa pakietu jest znana tylko w środowisku wykonawczym?

import messages_en # it works 
messages = __import__('messages_en') # it doesn't ? 

Kiedyś myślałem 'import X' jest po prostu kolejnym sposobem na powiedzenie __import__('x')

Odpowiedz

14

Dodawanie argument globals jest wystarczająca dla mnie:

__import__('messages_en', globals=globals()) 

W rzeczywistości, tylko __name__ jest potrzebne tutaj:

__import__('messages_en', globals={"__name__": __name__}) 
14

__import__ jest funkcja wewnętrzna wywoływana przez instrukcję importu. W codziennej kodowania nie trzeba (lub chce), aby wywołać __import__

z dokumentacją Pythona:

na przykład oświadczenie import spam skutkuje kodu bajtowego przypominające następujący kod:

spam = __import__('spam', globals(), locals(), [], -1) 

Na Natomiast komunikat from spam.ham import eggs, sausage as saus skutkuje

_temp = __import__('spam.ham', globals(), locals(), ['eggs', 'sausage'], -1) 
eggs = _temp.eggs 
saus = _temp.sausage 

więcej informacji: http://docs.python.org/library/functions.html

+1

+1 i dzięki za wyjaśnienie, ale może właśnie dlatego można opisać Przykład OP nie działa? Wydaje się, że stara się alias messages_en do wiadomości, co wydaje się (naiwnie dla mnie) uzasadnione. –

+0

Jak wyjaśnił "wr", to wynikało z poziomu i wiem, że __import__ nie powinien być zwykle używany, ale w tym przypadku muszę dynamicznie czytać język z pliku konfiguracyjnego dodawać do wiadomości i importować ten plik –

+0

Ten przykład był bardzo pomocny, zwłaszcza jeśli próbujesz wczytać moduły z podkatalogów. Pomogło mi naprawić błąd "Nie znaleziono atrybutu". – Carlos

19

Jeśli jest to problem, ścieżka, należy użyć level argumentu (z docs):

__import__(name, globals={}, locals={}, fromlist=[], level=-1) -> module 

Level is used to determine whether to perform 
absolute or relative imports. -1 is the original strategy of attempting 
both absolute and relative imports, 0 is absolute, a positive number 
is the number of parent directories to search relative to the current module. 
+2

ale zastanawiam się, jaki był powód, ponieważ domyślny poziom to -1, a ja wciąż przechodzę -1, więc tylko dodatkowy jest globalny/lokalny dykt, jak to robi różnicę –

+0

Dlaczego jest to zaakceptowana odpowiedź? Nie odpowiada ani na pytanie, ani nie rozwiązuje problemu. – kynan

+0

Ta odpowiedź jest błędna. Problem PO nie jest w żaden sposób związany z "poziomem". Dwie opcje, aby to naprawić: Podaj globale modułu jako 'messages = __import __ ('messages_en', globals())' jak Eric wskazuje lub podaje nazwę pakietu, jak sugeruje Lennart. – kynan

0

Można spróbować to:

messages == __import__('Foo.messages_en', fromlist=['messages_en']) 
3

Pamiętaj, aby dołączyć do katalogu modules do twojej ścieżki Pythona.

Twoja ścieżka (lista katalogów, w których Python przechodzi do wyszukiwania modułów i plików) jest przechowywana w atrybucie ścieżki modułu sys. Ponieważ ścieżka jest listą, możesz użyć metody append do dodania nowych katalogów do ścieżki.

Na przykład, aby dodać katalog/home/ja/mypy do ścieżki:

import sys 
sys.path.append("/home/me/mypy") 
+1

To nie jest bezpieczne, ponieważ sprawia, że ​​opakowanie nie może zostać przeniesione. Będzie działać tylko wtedy, gdy pakiet znajduje się na tej zakodowanej ścieżce. – kynan

0

Musisz ręcznie zaimportować najwyższy pakiet ścieżki dynamicznego pakietu.

Na przykład na początku pliku i napisać:

import sites 

później w kodzie to działa dla mnie:

target = 'some.dynamic.path' 
my_module = __import__ ('sites.%s.fabfile' % target, fromlist=["sites.%s" % target]) 
Powiązane problemy