先说一下 sys.path
这个变量,该变量需要导入 sys 官方库方可使用,它是一个列表,是当前 python 文件 import 库时会逐个搜索列表中的路径。
sys.path
从这些位置初始化:
PYTHONPATH
(目录名列表,与 shell 变量 PATH
语法相同)为了解决上述问题,需要添加模块搜索路径,可以使用以下几种方式:
动态增加路径
临时生效,对于不经常使用的模块,这通常是最好的方式,因为不必用所有次要模块的路径来污染 PYTHONPATH。
import sys
sys.path.append('/home/song/mylib')
修改 PYTHONPATH 变量
永久生效,对于在许多程序中都使用的模块,可以采用这种方式。这将改变所有 Python 应用的搜索路径,因为启动 Python 时,它会读取这个变量,甚至不同版本的 Python 都会受影响。
export PYTHONPATH=$PYTHONPATH:/home/song/mylib
直接命令行执行则当前终端生效,或添加到 ~/.bashrc
中并 source 永久生效。
增加 .pth 文件
永久生效,这是最简单的、也是推荐的方式。Python 在遍历已知的库文件目录过程中,如果遇到 .pth 文件,便会将其中的路径加入到 sys.path 中,于是 .pth 中所指定的路径就可以被 Python 运行环境找到了。
在 /usr/local/lib/python3.5/site-packages
下添加一个扩展名为 .pth
的配置文件(例如:extras.pth
),内容为要添加的路径:/home/song/mylib
。
考虑这样一个目录结构,他基本涵盖我们 python 文件 import 自定义库时的情况:
.
├── lib1.py
├── t1
│ ├── lib0.py
│ └── test.py
└── t2
└── lib2.py
我们的 test.py
想要 import lib0、1、2.py
三个库文件,并且,我们要考虑在 test.py
的当前目录运行(python test.py
) 或其父目录运行(python t1/test.py
)时,分别应该怎么做呢?
当前目录运行
首先要明确,我们的 python 程序在考虑相对路径时,考虑的是文件所在目录的相对路径,而不是工作目录的路径。所以我们直接导入即可:
import lib0
父目录运行
刚才提到这不受到工作目录影响,所以同上。
当前目录运行
我们都知道,要导入上级目录的文件,可以通过在 sys.path
中追加上级目录 ..
来实现。另一个关键点就在这里,sys.path
中的相对路径是相对工作目录而言的,而不是相对文件所在目录。因此我们在当前目录运行时:
import sys
sys.append('..')
import lib1
运行:python test.py
。
父目录运行
注意这里就有所不同了,因为 sys.path
是相对工作目录而言的,我们在父目录运行程序,工作目录变化了,因此应该:
import sys
sys.append('.')
import lib1
实际导入 lib2 就与导入 lib1 类似,只是多一级即可
当前目录运行
import sys
sys.append('..')
import t2.lib1
父目录运行
import sys
sys.append('.')
import t2.lib1
Ref:
Python 模块搜索路径