11

I encounted something strange about python import statement.

Let's say that I have a file structure like below:

foo\
 __init__.py
 bar.py
 os.py

Codes in bar.py (Other files are empty)

import os
print os.__file__

The strange thing is when I run python -m foo.bar, it prints

foo/os.pyc

However, when I changed direcotry to foo, and run python -m bar, it prints

/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc

What's the difference between the two ways I run script?

In a word, what's the order Python used to import module?

From official documents, I found several text about this problem (They made me even more confused)

  1. 6.1.2. The Module Search Path

the interpreter first searches for a built-in module with that name. If not found, it then searches for a file named spam.py in a list of directories given by the variable sys.path.

  1. sys.path

the first item of this list, path[0], is the directory containing the script that was used to invoke the Python interpreter. If the script directory is not available (e.g. if the interpreter is invoked interactively or if the script is read from standard input), path[0] is the empty string, which directs Python to search modules in the current directory first.

  1. 6.4.2. Intra-package References

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.

...

If the imported module is not found in the current package (the package of which the current module is a submodule), the import statement looks for a top-level module with the given name.

asked Aug 6, 2015 at 7:26

1 Answer 1

5

What's the difference between the two ways I run script?

The difference is if foo is (from python's view) a loaded module or not.

If you run python -m foo.bar, foo is a valid module. Even with Python 2.7, import os is still a relative import and hence os gets resolved against the containing module (i.e. foo), first:

https://docs.python.org/2/tutorial/modules.html#intra-package-references:

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.

When you run python -m bar, bar is a top level module, i.e. it has no containing module. In that case import os goes to through sys.path.

The default module search for an import bla is

  1. If a containing module exists, do a relative import against the containing module.
  2. Go into sys.path and use the first successful import.

To disable (1), you can

from __future__ import absolute_import 

at the very top of a module.

Confusing? Absolutely.

answered Aug 6, 2015 at 8:04
Sign up to request clarification or add additional context in comments.

1 Comment

[containing package] > built-in module > sys.path

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.