tags:

views:

38

answers:

1

I was trying out one of the Python standard library modules, let's call it foo.bar.baz.

So I wrote a little script starting with

import foo.bar.baz

and saved it as foo.py.

When I executed the script I got an ImportError. It took me a while (I'm still learning Python), but I finally realized the problem was how I named the script. Once I renamed foo.py to something else, the problem went away.

So I understand that the import foo statement will look for the script foo.py before looking for the standard library foo, but it's not clear to me what it was looking for when I said import foo.bar.baz. Is there some way that foo.py could have the content for that statement to make sense? And if not, why didn't the Python interpreter move on to look for a directory hierarchy like foo/bar with the appropriate __init__.py's?.

+3  A: 

An import statement like import foo.bar.baz first imports foo, then asks it for bar, and then asks foo.bar for baz. Whether foo will, once imported, be able to satisfy the request for bar or bar.baz is unimportant to the import of foo. It's just a module. There is only one foo module. Both import foo and import foo.bar.baz will find the same module -- just like any other way of importing the foo module.

There is actually a way for foo to be a single module, rather than a package, and still be able to satisfy a statement like import foo.bar.baz: it can add "foo.bar" and "foo.bar.baz" to the sys.modules dict. This is exactly what the os module does with os.path: it imports the right "path" module for the platform (posixpath, ntpath, os2path, etc), and assigns it to the path attribute. Then it does sys.modules["os.path"] = path to make that module importable as os.path, so a statement like import os.path works. There isn't really a reason to do this -- os.path is available without importing it as well -- but it's possible.

Thomas Wouters
+1 Nice answer, and good motivation to read up on the whole import process. When you say the import statement [asks foo] to import bar, are you using the word 'ask' loosely, or is there some method that is called?
brainjam
I already changed the wording because I realized that was probably going to be taken too literally :) The `__import__` function does all the actual importing, but it does import `foo` first, then it re-starts the entire import procedure for `foo.bar` -- which means that (among other things) it looks in `sys.modules['foo.bar']` and examines `sys.modules['foo'].__path__`.
Thomas Wouters
Oops. Time to delete my answer because I'm wrong. :-)
Omnifarious