Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python import package - subpackage should not show up in symbol table

Tags:

python

I am wondering why the directory (subpackage) that holds submodules in a python package shows up as a symbol when the package is imported. For instance, if I have this package:

PyModTest/                        Top-level package
          __init__.py             Initialize the package
          Source/                 Subpackage holding source files
                 __init__.py
                 WildMod.py        Submodule containing a function: 'WildFunc'

where the top level __init__.py looks like this:

#!/usr/bin/env python

from Source.WildMod import WildFunc

and, for completeness' sake, the lower level __init__.py looks like this:

#!/usr/bin/env python

__all__ = ["WildMod"]

OK, so now I open up the interpreter, import the module, and look at the symbols:

>>> import PyModTest
>>> dir(PyModTest)
['Source', 'WildFunc', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__']

SEE, the 'Source' module shows up, even though I never specifically imported it!

The only symbol (besides the private ones) that I want to see is my 'WildFunc'. Is there any way to hide the 'Source' package?

like image 310
rokuingh Avatar asked Dec 17 '11 00:12

rokuingh


1 Answers

Two things to note here:

  • In Python, modules are actual objects, and the dot that appears between their names represents an actual attribute access
  • You are doing a relative import, meaning that Source is actually PyModTest.Source (thanks to TokenMacGuy for pointing this out)

So: in order to import PyModTest.Source.WildMod.WildFunc, Python has to

  1. import PyModTest (which was already done by you)
  2. check and see if it has an attribute called Source, and if not, create the attribute by importing it from PyModTest/Source/__init__.py
  3. check and see if that has an attribute called WildMod, and if not, create the attribute by importing it from PyModTest/Source/WildMod.py
  4. check and see if that has an attribute called WildFunc (which it does)

Some relevant details are discussed in PEP 302 and in the Python language reference.

Deeper down in the mechanism, a dotted name import is split up by its components. For "import spam.ham", first an "import spam" is done, and only when that succeeds is "ham" imported as a submodule of "spam".

If you don't want to have a variable named Source, that's easy to fix: just del Source after you import the function. But bear in mind that it will prevent any code that runs later on from accessing PyModTest.Source.<anything> (except for WildFunc, since you have saved a reference to that). I would definitely suggest just ignoring the reference to Source, not deleting it, since it's not hurting anything.

like image 96
David Z Avatar answered Nov 06 '22 14:11

David Z