Python sys.path与-m参数的作用
sys.path作用
sys.path当试图导入一个模块时,Python解释器会按照sys.path中列出的路径顺序搜索对应的模块文件。
sys.path的组成包括当前目录(即包含你当前运行脚本的目录)
PYTHONPATH环境变量中列出的路径
Python标准库的路径,以及其他安装的第三方库的路径
通过修改sys.path,可以控制Python解释器搜索模块的顺序,这对于动态添加或修改模块搜索路径非常有用。
验证
创建一个目录层级方便导包测试,以下是创建的目录结构
[ldsx@master ]$ tree python_code/
python_code/
└── src_code
├── ldsx_cfg
│ ├── test_cfg.py
│ └── test_mail.py
├── ldsx_db
│ └── test_db.py
├── ldsx_utils
│ └── test_utils.py
└── test_main.py
在test_main.py中导入包写入一下内容
import sys
import os
import traceback
try:
from ldsx_cfg.test_cfg import *
except Exception:
traceback.print_exc()
if __name__ == '__main__':
print('PATH', sys.path)
print('PWD', os.getcwd())
使用终端执行
可见当路径在/home/ldsx/ldsx_code/ldsx_improve/python_code下执行没问题,导入包正常,
sys.pathd第一个元素是src_code这个路径
当前的工作路径为:/home/ldsx/ldsx_code/ldsx_improve/python_code
使用-m参数执行
当使用 -m模块运行的时候出现了 moduleNotFound,
sys.path第一个元素变成了''
当前的工作路径为:/home/ldsx/ldsx_code/ldsx_improve/python_code
当我们切换路径继续使用-m参数运行
切换路径到src_code中继续使用模块花运行,运行成功
当前sys.path第一个元素还是''
但是当前的工作路径为:/home/ldsx/ldsx_code/ldsx_improve/python_code/src_code
证明当使用 -m模块执行的时候,sys.ptah的’'为当前的工作路径。
刚才是在test_mian中导入与test_main同层文件夹下的文件,这次使用ldsx_utils文件夹下的test_utils.py导入
ldsx_cfg下的test_cfg.py
#打开test_utils.py写入一下内容
class LdsxFunc():
pass
import sys
import os
import traceback
try:
from ldsx_cfg.test_cfg import *
except Exception:
traceback.print_exc()
if __name__ == '__main__':
print('PATH', sys.path)
print('PWD', os.getcwd())
无法找到文件,因为sys.path第一个元素的路径:/home/ldsx/ldsx_code/ldsx_improve/python_code/src_code/ldsx_utils
根本不包含ldsx_cfg这个文件夹所以肯定找不到
在import sys下添加一行
sys.path.append('/home/ldsx/ldsx_code/ldsx_improve/python_code/src_code')
再次执行
使用-m 模块化执行
删掉sys.path.append('/home/ldsx/ldsx_code/ldsx_improve/python_code/src_code')
结论
python导入包的时候会使用sys.path中的路径去寻找包,如果sys.path中的路径,这个路径目录下不包含你要找的包(文件夹)那么导入一定会失败,
当使用-m参数提交,意义就是把你当前的工作目录作为找包路径,在sys.path中体现为第一个元素是’',
不使用-m参数sys.path会把你执行文件的绝对路径当作找包路径,这就是区别。
文件a,引用文件b,文件b的sys.path的表现
在文件a中引用文件b,文件b的sys.path,会变成执行文件a时候的路径
ldsx_utils下的test.utlis
#ldsx_utils下的test.utlis
class LdsxFunc():
pass
import sys
import os
import traceback
try:
from ldsx_cfg.test_cfg import *
except Exception:
traceback.print_exc()
print('test_utils PATH', sys.path)
print('test_utils PWD', os.getcwd())
if __name__ == '__main__':
print('PATH', sys.path)
print('PWD', os.getcwd()
src_code下的test_main.py,在test_main.py下引用ldsx_utils.test_utils
import sys
import os
import traceback
try:
from ldsx_cfg.test_cfg import *
except Exception:
traceback.print_exc()
from ldsx_utils.test_utils import *
if __name__ == '__main__':
print('PATH', sys.path)
print('PWD', os.getcwd())
执行结果
[ldsx@master src_code]$ python3 test_main.py
test_utils PATH [
'/home/ldsx/ldsx_code/ldsx_improve/python_code/src_code', 可见test_utils路径变成了 test_main.py的路径
'/home/ldsx/down_load/python_data/python3.6.8/lib/python36.zip', '/home/ldsx/down_load/python_data/python3.6.8/lib/python3.6', '/home/ldsx/down_load/python_data/python3.6.8/lib/python3.6/lib-dynload', '/home/ldsx/down_load/python_data/python3.6.8/lib/python3.6/site-packages']
test_utils PWD /home/ldsx/ldsx_code/ldsx_improve/python_code/src_code
PATH ['/home/ldsx/ldsx_code/ldsx_improve/python_code/src_code', '/home/ldsx/down_load/python_data/python3.6.8/lib/python36.zip', '/home/ldsx/down_load/python_data/python3.6.8/lib/python3.6', '/home/ldsx/down_load/python_data/python3.6.8/lib/python3.6/lib-dynload', '/home/ldsx/down_load/python_data/python3.6.8/lib/python3.6/site-packages']
PWD /home/ldsx/ldsx_code/ldsx_improve/python_code/src_code
所以当创建好项目后,确认根目录,以根目录导包,便于导包管理
pycharm可通过设置Sources root配置sys.path路径
注意
使用相对路径导入包并不优雅
1.当你使用相对路径导入包,你想单独运行这个导入包脚本,sys.path会找不到路径。
2.当调整目录层级的时候相对路径也需要修改,不能直接使用。