16

I have a messages folder(package) with __init__.py file and another module messages_en.py inside it. In __init__.py if I import messages_en it works, but __import__ fails with "ImportError: No module named messages_en"

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

I used to think 'import x' is just another way of saying __import__('x')

CharlesB
  • 86,532
  • 28
  • 194
  • 218
Anurag Uniyal
  • 85,954
  • 40
  • 175
  • 219

7 Answers7

21

If it is a path problem, you should use the level argument (from 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.
Jorge E. Cardona
  • 92,161
  • 3
  • 37
  • 44
wr.
  • 2,841
  • 1
  • 23
  • 27
  • 2
    but I wonder what was the reason , because default level is -1, and I am still passing -1, so only extra are global/local dict, how that makes a difference – Anurag Uniyal Jun 29 '09 at 12:57
  • Why is this the accepted answer? It does neither answer the question nor fix the problem. – kynan Feb 22 '13 at 21:24
  • This answer is wrong. The OP's problem is not related to `level` in any way. Two options to fix it: Either supply the module's globals as `messages = __import__('messages_en', globals())` as Eric points out or give the package name as Lennart suggests. – kynan Feb 23 '13 at 00:28
  • 2
    in Python 3, level must be >=0. set it to 1 in this case. – UXkQEZ7 Feb 12 '15 at 06:43
20

Adding the globals argument is sufficient for me:

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

In fact, only __name__ is needed here:

__import__('messages_en', globals={"__name__": __name__})
Eric
  • 95,302
  • 53
  • 242
  • 374
14

__import__ is an internal function called by import statement. In everyday coding you don't need (or want) to call __import__

from python documentation:

For example, the statement import spam results in bytecode resembling the following code:

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

On the other hand, the statement from spam.ham import eggs, sausage as saus results in

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

more info: http://docs.python.org/library/functions.html

Perica Zivkovic
  • 2,610
  • 24
  • 32
  • 1
    +1 and thanks for explanation, but could you describe exactly why OP's example doesn't work? He seems to be trying to alias messages_en to messages, which seems (naively to me) to be reasonable. –  Jun 29 '09 at 11:54
  • As 'wr' explained it was due to level, and I know __import__ shouldn't be usually used but in this case i have to dynamically read language from a config file append to messages and import that file – Anurag Uniyal Jun 29 '09 at 12:55
  • This example was very helpful, especially if you're trying to load modules from subdirectories. It helped me fix my "Attribute not found" error. – Carlos Oct 18 '12 at 15:46
  • @AnuragUniyal no, your example didn't work due to the missing `globals()`, the default value for `level` is fine. – kynan Feb 23 '13 at 00:42
4

Be sure to append the modules directory to your python path.

Your path (the list of directories Python goes through to search for modules and files) is stored in the path attribute of the sys module. Since the path is a list you can use the append method to add new directories to the path.

For instance, to add the directory /home/me/mypy to the path:

import sys
sys.path.append("/home/me/mypy") 
Upgrayd
  • 41
  • 1
  • 2
    That's not safe since it makes the package not relocatable. It will only work if the package is in this hard coded path. – kynan Feb 23 '13 at 00:24
4

I understand that this question is about the __import__() function but I think the importlib package is best suited for run-time package imports if you are using Python 2.7 or above as advised in the doc:

Note: Programmatic importing of modules should use import_module() instead of this function.

Possible Gotcha: This was introduced in python 2.7:

New in version 2.7.

This module is a minor subset of what is available in the more full-featured package of the same name from Python 3.1 that provides a complete implementation of import. What is here has been provided to help ease in transitioning from 2.7 to 3.1.

In your case, you may use:

import importlib

messages = importlib.import_module('messages_en')

Also, if you wanted to specify the package name, then from messages import messages_en may be written as:

importlib.import_module('.messages_en', 'messages')

Note the . in .messages_en used for relative path resolution as described here:

... The name argument specifies what module to import in absolute or relative terms (e.g. either pkg.mod or ..mod). If the name is specified in relative terms, then the package argument must be set to the name of the package which is to act as the anchor for resolving the package name (e.g. import_module('..mod', 'pkg.subpkg') will import pkg.mod).

Community
  • 1
  • 1
Chukwuemeka
  • 342
  • 6
  • 11
  • None of the other answers or assumptions are valid anymore. Thanks for the importlib, Chukwuemeka! Finally solved a question I had! – Vaidøtas I. Mar 24 '20 at 22:08
2

You could try this:

messages == __import__('Foo.messages_en', fromlist=['messages_en'])
Lennart Regebro
  • 167,292
  • 41
  • 224
  • 251
0

You need to manually import the top package of your dynamic package path.

For example in the beginning of the file i write:

import sites

then later in code this works for me:

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