2

Why do I have to import all sub-packages if I want to use them?
I'll explain myself with an example:

In [1]: import cime In [2]: cime.runners --------------------------------------------------------------------------- AttributeError Traceback (most recent call last) /home/miki/testit/<ipython-input-2-35e09c66121a> in <module>() ----> 1 cime.runners AttributeError: 'module' object has no attribute 'runners' In [3]: import cime.runners In [4]: cime.runners Out[4]: <module 'cime.runners' from '/home/miki/testit/venv/lib/python2.7/site-packages/cime/runners/__init__.pyc'> 

As you can see it's a regular Python package:

In [5]: cime.__file__ Out[5]: '/home/miki/testit/venv/lib/python2.7/site-packages/cime/__init__.pyc' In [6]: ls /home/miki/testit/venv/lib/python2.7/site-packages/cime download.py __init__.py log.py runners/ run.pyc utils.pyc download.pyc __init__.pyc log.pyc run.py utils.py 

But this does not happens with built-in modules. Why?

In [7]: import os # instead of import os.path In [8]: os.path Out[8]: <module 'posixpath' from '/home/miki/testit/venv/lib/python2.7/posixpath.pyc'> 

Thanks,
rubik

P.S. I'm inside a virtualenv, but I don't know if that matters.

2 Answers 2

2

This is a design decision by the cime (whatever that is) developers. A package does not magically import all of its subpackages. That's a good thing, because otherwise large packages like SciPy would take forever to import (like NLTK does).

Some packages, like os.path, NumPy and NLTK will import submodules, but they do so explicitly. If you want this to happen in your own module, do

# __init__.py import .submodule 
Sign up to request clarification or add additional context in comments.

2 Comments

I'd say: os.path is an exception rather than a rule. import a doesn't imply import a.b or import a.c in Python.
Yes, I now looked to os.py source and it does import modules explicitly. hg.python.org/cpython/file/290d970c011d/Lib/os.py
1

os.path is an exception related to an implementation detail. Python is generally conservative about how much work it will do, and so it only imports modules you actually ask for. Because the actual implementation of os.path is rather dependent on your operating system, python works out which implementation you need, and imports it as os.path at python start-up time.

You can get a very similar effect, if that's something you want, by adding some additional imports to your cime/__init__.py

from cime import runners 

and so on.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.