I’ve almost never been able to write correct Python import
statements on the first go. Behavior is inconsistent between Python 2.7 and Python 3.6 (the two versions that I test here), and there is no single method for guaranteeing that imports will always work. This post is my dive into how to resolve common importing problems. Unless otherwise stated, all examples here work with both Python 2.7 and 3.6.
import
statements search through the list of paths in sys.path
sys.path
always includes the path of the script invoked on the command line and is agnostic to the working directory on the command line.__init__.py
file*.py
file. Its name is the file name.*.py
file.__init__.py
in it. Its name is the name of the folder.
__init__.py
file) is considered a packagetest/ # root folder
packA/ # package packA
subA/ # subpackage subA
__init__.py
sa1.py
sa2.py
__init__.py
a1.py
a2.py
packB/ # package packB (implicit namespace package)
b1.py
b2.py
math.py
random.py
other.py
start.py
Note that we do not place a __init__.py
file in our root test/
folder.
import
?When a module is imported, Python runs all of the code in the module file. When a package is imported, Python runs all of the code in the package’s __init__.py
file, if such a file exists. All of the objects defined in the module or the package’s __init__.py
file are made available to the importer.
import
and sys.path
According to Python documentation, here is how an import
statement searches for the correct module or package to import:
When a module named
spam
is imported, the interpreter first searches for a built-in module with that name. If not found, it then searches for a file namedspam.py
in a list of directories given by the variablesys.path
.sys.path
is initialized from these locations:
- The directory containing the input script (or the current directory when no file is specified).
PYTHONPATH
(a list of directory names, with the same syntax as the shell variable PATH).- The installation-dependent default.
After initialization, Python programs can modify
sys.path
. The directory containing the script being run is placed at the beginning of the search path, ahead of the standard library path. This means that scripts in that directory will be loaded instead of modules of the same name in the library directory.Source: Python 2 and 3重要内容翻译: 当需要导入spam模块时,解释器首先在内建的模块中搜索。如果没有找到,就会在变量sys.path指向的文件夹列表中搜索,这些文件夹列表在一个list中包含。sys.path初始化时,指向以下文件夹:
- 当前python脚本所在的文件夹(如果没有指定python脚本,则是当前文件夹)
- 环境变量PYTHONPATH(文件夹列表,和shell中的环境变量PATH语法相同)
- 默认的依赖安装
初始化完成之后,可以在程序中修改sys.path 。 当前python脚本所在目录,将会被放在list的开头,然后是标准库的所在目录。 这意味着,如果当前脚本所在的目录如果有和标准库所在目录,如果有相同module的话,自己的module将优先被加载到。
参考下文中的举例:自定义的random.py和系统的random.py的比较。已经用红色字体标注
Technically, Python’s documentation is incomplete. The interpreter will not only look for a file (i.e. module) named spam.py
, it will also look for a folder (i.e. package) named spam
.
Note that the Python interpreter first searches through the list of built-in modules, modules that are compiled directly into the Python interpreter. This list of built-in modules is installation-dependent and can be found in sys.builtin_module_names
(Python 2 and 3). Some built-in modules that are commonly included are sys
(always included), math
, itertools
, and time
, among others.
Unlike built-in modules which are first in the search path, the rest of the modules in Python’s standard library (not built-ins) come after the directory of the current script. This leads to confusing behavior: it is possible to “replace” some but not all modules in Python’s standard library. For example, on my computer (Windows 10, Python 3.6), the math
module is a built-in module, whereas the random
module is not. Thus, import math
in start.py
will import the math
module from the standard library, NOT my own math.py
file in the same directory. However, import random
in start.py
will import my random.py
file, NOT the random
module from the standard library.
Also, Python imports are case-sensitive. import Spam
is not the same as import spam
.
The function pkgutil.iter_modules
(Python 2 and 3) can be used to get a list of all importable modules from a given path:
import pkgutil
search_path = '.' # set to None to see all modules importable from sys.path
all_modules = [x[1] for x in pkgutil.iter_modules(path=search_path)]
print(all_modules)
Sources
sys.path
To see what is in sys.path
, run the following in the interpreter or as a script:
import sys
print(sys.path)
Python’s documentation for sys.path
describes it as…
A list of strings that specifies the search path for modules. Initialized from the environment variable
PYTHONPATH
, plus an installation-dependent default.As initialized upon program startup, 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. Notice that the script directory is inserted before the entries inserted as a result ofPYTHONPATH
.Source: Python 2 and 3
The documentation for Python’s command line interface adds the following about running scripts from the command line. Specifically, when running python