python
python

Reputation: 1940

How to get current module being imported in the __init__.py file?

package
    1) module1
    2) module2
    3) module3
    4) __init__.py

what I want to do is

  1. import package
  2. then I could use some sub modules in module1, module2 directly, just looks like if I have imported it in the following way:

    import module1
    

If I use imp.load_module in __init__.py to load module1, then dir(package1) will have "module1", "module2" in sys.modules, but I still need to use package.modules1 to access it. I noticed that when I import package, I will get a 'module' object package. If I update the package's built-in method, it will trick the system to make module1 visible.

>>> import package
>>> package.__dict__.update(package.module1.__dict__)

then everything looks fine and it seems to python the module1 has been imported like import module1 and I could use class or modules in module1 directly.

Then comes up my question --- How to detect currently module object in __init__.py? I tried imp.find_module, but it seems it doesn't return a module object.

OK , I update the problem here. First , module1 is really what I want to use in code, but It depends on module2 and module3, and both module1 , module2 and module3 are from opensource code. In order to keep it in sync with the newest version, so module1,2,3 remains what it look like after unzipped. We need to wrapper module1 to provdide some interface to other guys, they expected module1 is visible when calling "import module1" However, as it depends on module2,3 , so it is not callable. So I want to wrapper it in a new "package", or just rename the "package" to "module1", so when others call "import package", it will transparently make the module1 namespace visible to caller. I now could use imp.load_module to load module1, but when I called dir(package), it looks like this:

 >>> import package
>>> print dir(package)
    ['__all__', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'module1']
>>> print type(package.modue1)
 type<'module'>

So module1 is still not directly visible to the caller. I noticed that I could update the attribute and member function of a module if I use tricky way like this:

>>> import package (this will triger calling __init__.py)
>>> package.__dict__.update(package.module1.__dict__)

after this, everything looks like if I have just called "import module1". However, I could not get a module object after "import" return, I wonder if there is any method to upload the module dict in init.py ?

Upvotes: 2

Views: 1600

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1124738

Why do you want to do this? Explicit is better than implicit!

Import everything your API wants to expose in __init__ then let people use from package import * instead. Use __all__ to explicitly list what should be exported that way.

In __init__.py, use:

import module1
import module2

__all__ = ['module1', 'module2']

and leave importing everything to your users. They should have the choice, not have the modules forced upon them.

Or, if you meant items from the nested modules to be visible in package, import those explicitly, or use from modulename import * there too (but do add an __all__ list to such modules):

from module1 import *
from module1 import __all__ as module1_exported
from module2 import *
from module2 import __all__ as module2_exported

__all__ = module1_exported + module2_exported

Adding items to __builtins__ means you made the names visible everywhere, not just to whatever imported your package. Rarely is there a need to mess with built-ins.

Upvotes: 1

Related Questions