Reputation: 149
I am new to Python and the 'import' in Python is confusing me. It seems that it sometimes imports functions in the module recursively and sometimes doesn't.
For example, if I do
import numpy
then I can use all the functions in numpy, including the functions in the 'sub-modules' (not sure if it is a proper name), such as
a = numpy.fft.fft2(b)
c = numpy.random.rand()
However, if I do
import skimage
I can not use functions in the 'sub-modules' of skimage, such as
skimage.color.rgb2gray()
skimage.transform.resize()
I have to import the 'sub-modules' explicitly as
from skimage import color
from skimage import transform
So how to know whether import will work recursively for a module? And why does Python not make it consistent for all modules?
Upvotes: 0
Views: 569
Reputation: 40888
What you're seeing isn't recursion. It's a case where some functions are being brought into the namespace of submodules.
From the skimage docs:
The main package of
skimage
only provides a few utilities for converting between image data types; for most features, you need to import one of the following subpackages ...
In short, color
is not a module; its a fully bonafide package-within-a-package. A package's __init__.py
defines what gets brought into its namespace. When you see "skimage has no attribute 'color'", that's because the top-level package skimage only has these things available:
[f for f in dir(skimage) if not f.startswith('_')]
['data_dir',
'doctest',
'doctest_verbose',
'dtype_limits',
'img_as_bool',
'img_as_float',
'img_as_int',
'img_as_ubyte',
'img_as_uint',
'pkg_dir',
'test',
'test_verbose',
'util']
Now, check out the __init__.py
from NumPy:
from . import core
from .core import *
from . import compat
from . import lib
from .lib import *
from . import linalg
# ... and so on
(Nothing equivalent is being done in the skimage __init__.py
)
All of these sub-packages are now fully available with attribute dot-notation access; and, all of the functions from .lib
are now also acccessible via np.<function>
because they are imported here as well.
You can see this difference for yourself with a simple nested package structure. Make this on your local drive:
sound/
__init__.py
subpackage1/
__init__.py
submodule1.py
subpackage2/
__init__.py
submodule2.py
Now, in the top-level __init__.py
, put just from sound.subpackage1 import submodule1
. (Don't reference subpackage2.) Now if you cd
into one level above sound, and do import sound
, try using tab completion. You'll see that submodule1
and subpacakge1
are directly available with dot notation, but the other sub-package is not.
Here's one other note: the full path to rgb2gray
is actually skimage/color/colorconv/rgb2gray
. Why is it accessible from color
? Because it's imported within the __init__.py
of color.
To your last question:
So how to know whether import will work recursively for a module? And why does Python not make it consistent for all modules?
There's not a lot of predictable consistency between packages regarding whether they make these imports internally. Typically, large "nested" libraries such as pandas and NumPy do. In the case of skimage, its designers might have wanted to keep its subpackages "distinct" because some of them offer very different functionality, even if they are image-related.
Upvotes: 3