views:

110

answers:

3

Apologies in advange for the newbie question. I can't get my head around this, and the docs don't help!

Consider the following directory structure:

spam.py
foo     / __init__.py
          ham.py
          eggs.py

with the following code:

# __init__.py
# blank

# ham.py
print( "got ham!" )

# eggs.py
print( "got eggs, importing ham!" )
import foo.ham

Now, if I import foo.eggs inside spam.py (!), the right thing happens and all the module references work.

BUT

If I try and execute eggs.py directly, I get an ImportError: No module named foo.ham! If I change the foo.ham imports to just ham, the right thing happens... but then I can't import foo.eggs!

So, how do I develop eggs? If I use 'undotted' references, I can develop fine, but can't try it out because I can't import the module! If I use the full foo.ham reference, I can import the package, but can't execute the submodule for development purposes!

Is this just a glitch with Python's packaging architecture? Am I doing it wrong?

+1  A: 

The parent directory for foo needs to be in the python's path:

$ ls foo
eggs.py  ham.py  ham.pyc  __init__.py  __init__.pyc
$ python foo/ham.py
got ham!
$ python foo/eggs.py
got eggs, importing ham!
Traceback (most recent call last):
  File "foo/eggs.py", line 2, in <module>
    import foo.ham
ImportError: No module named foo.ham
$ PYTHONPATH=. python foo/eggs.py
got eggs, importing ham!
got ham!
MattH
A: 

This seems to work: Here is the directory structure:

~/test/kl% ls -R
.:
foo  spam.py

./foo:
eggs.py  eggs.pyc  ham.py  ham.pyc  __init__.py  __init__.pyc

Here are the file contents:

~/test/kl% cat spam.py 
import foo.eggs

~/test/kl% cd foo/
~/test/kl/foo% cat eggs.py
print( "got eggs, importing ham!" )
import ham

We can import ham from spam.py, and foo/eggs.py:

~/test/kl% python spam.py 
got eggs, importing ham!
got ham!

A useful rule to remember is that when you say python script.py, the directory containing script.py is added to the beginning of sys.path, the directories searched for modules. That's why python spam.py works without changing PYTHONPATH.

~/test/kl% python foo/eggs.py
got eggs, importing ham!
got ham!

Here, ~/test/kl/foo is added to the sys.path. That's okay, because eggs.py tries to import ham. Since ham.py resides in ~/test/kl/foo which is in sys.path, Python finds it just fine.

~/test/kl% cd foo
~/test/kl/foo% python eggs.py
got eggs, importing ham!
got ham!

The directory ~/test/kl was not in my PYTHONPATH.

unutbu
Ugh. Still doesn't work for me, I wonder if it's a Linux thing? I don't have access to Linux atm unfortunately...
katrielalex
Are you sure you didn't modify your `spam.py` while writing this? I have literally checked my files ten times, and `python spam.py` does not work.
katrielalex
@katrielalex: I just checked again. The file contents are as I've posted.
unutbu
You might want to try removing any old .pyc, .pyw files.
unutbu
A: 

This is a Python's packaging architecture. Normally a module can import modules either from current directory with dotted reference, either from $PYTHONPATH directory. You should understand that a module reference is just relative path to this module. So... an interpreter can't import any module that's not found on file system.

eigenein
I quote the docs: The submodules often need to refer to each other. For example, the surround module might use the echo module. In fact, such references are so common that the import statement first looks in the containing package before looking in the standard module search path... see http://docs.python.org/tutorial/modules.html#intra-package-references
katrielalex