You can investigate this by inspecting sys.path
in an interactive interpreter. What you'll find is that the first element of it is the location of the script the interpreter was told to run. This means that when you run your script at the top level (the location of the pack
package), that location is added to sys.path
automatically. It doesn't have anything to do with the actual package structure, so if you ran mod1.py
as a script you would have things break (this is probably why you put your script at the top level!).
Note that in Python 2, you also have the issue of implicit relative imports, which doesn't impact the issue you're asking about, but might come up if you had a few more modules involved. If you added mod3.py
to sub1
, you could import it from mod1
with just import mod3
, with the pack.sub1
prefix being figured out implicitly. This implicit behavior is generally considered a bad thing, and in Python 3 such implicit relative imports are not allowed (you can also disable them in Python 2 with from __future__ import absolute_import
). To import pack.sub1.mod3
from pack.sub1.mod1
you'd need to either name it in full, or use an explicit relative import: from . import mod3
To tie this relative import business back to your question, if you wanted to avoid relying on pack
being part of sys.path
(or, more realistically, protect against changes to pack
's name), you could modify your import of mod2
from mod1
to be an explicit relative import. Just use from .. import sub2.mod2
.