python中搜索路径


在Python中,搜索路径(search path)是用来搜索模块(module)或者包(package)的。
1. 基本概念
首先,明确两个基本概念:
工作目录(working directory,current directory) :外层命令行的位置;
脚本目录(script directory) :真正脚本所在位置。
这两个概念常常被很多人混淆,因为大部分人都习惯先cd到脚本所在的目录下,然后再执行
python xxx.py
。然而在某些情况下,脚本被保存在项目根目录的某一个子目录下,如果直接在项目根目录执行:
python ./some_dir/xxx.py
,二者就会出现差异。
在Python中,搜索目录主要包含如下三种来源:
- 脚本所在目录,即脚本目录;
-
全局的环境变量
PYTHONPATH
; -
利用sys包,直接
sys.path.insert
或者sys.path.append
而来的。
当你需要import一个库,或者一个包的时候,那么Python会首先去Python的原始安装目录下,以及上面的搜索路径之中(按顺序)去寻找,如果找不到则会抛出一个
ImportError
的异常。
2. 命令行和Pycharm的异同
有很多人都会使用Pycharm进行Python程序的开发,在Pycharm中,对于脚本目录和工作目录的处理是和命令行状态下,不尽相同的,这也造成了,一些程序在Pycharm下可以跑,在命令行中就会报无法import的错误,它们的区别是:
2.1. 命令行
在命令行中的情况,前文已经介绍过,脚本目录会被添加进搜索路径中,工作目录不被添加;
2.2. Pycharm
工作目录默认为脚本目录,也就是我们常使用的cd到脚本目录下再执行。此外,脚本目录和项目根目录(content root)都自动地被添加进搜索目录下;
对于第二点,可能是造成pycharm和命令行不一致的最大原因,相当于在执行每个脚本前手动地设置了一下
PYTHONPATH
或者
sys.path
,此时Pycharm内部的语法检查不会检查到错误。然而当你转到命令行里面去以后,没有设置项目根目录进搜索路径,就会出现找不到的情形。
3. 如何添加搜索目录
3.1. 脚本内部实现
import sys
sys.path.insert(0, "../")
sys.path为默认的搜索路径,可以在import某个库之前,及时地将库目录添加进搜索路径中。可以使用sys.path.insert或者sys.path.append两种方法。
可以使用相对路径,比如单个点号,两个点号等。 特别需要注意 ,在使用相对路径时,相对的是工作目录(working directory),就是外面命令行里面执行python语句的目录,而非脚本目录。
3.2. 添加环境变量
export PYTHONPATH=/home/libin:$PYTHONPATH
python ./script/main.py
上面的export语句也可以直接加入到
~/.bashrc
文件中,这样就可以永久性地将路径添加进搜索路径。但是不鼓励这样做,可能会污染搜索路径,因此我们还是更鼓励第一种方式。
4. 在运行时被引用模块的搜索路径
假如,执行一个脚本引用了另一个模块,被引用的模块内部,如何算搜索路径呢?举个例子,我们执行
python A.py
的脚本,
A.py
内部import了一个B.py的模块,比如:
import B
。
脚本的搜索路径,会被原封不动的传给模块,如果某个模块或者包,
A.py
能够import,那么在
B.py
内部也同样可以import。
还是要再一次强调,搜索路径里面的.或者..都是针对于工作目录的,这点也会被原封不动地由脚本传给模块