Reputation: 1940
package
1) module1
2) module2
3) module3
4) __init__.py
what I want to do is
package
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
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