Python中sys.path的用法
一 、 背景
在一个比较大的工程项目中,开发设计到的编程语言往往不止一个,每个语言负责项目中的某一块。在开发到了一定阶段,需要进行测试,需要将这些由各个语言负责的子模块合并到一起,然后统一测试,发版,上线。
目前我所做的项目中设计多门语言结合,所属的模块是用Python进行开发。因此其他语言开发的模块要调用py文件时,要从sys.path找到正确的模块目录,解释器才能正确调用。
因此今天就来聊一聊sys.path是什么?Python解释器是如何通过它来查找模块的?sys.path如何解决模块导入失败的问题?
二 、sys.path是什么?
sys.path变量指定了Python解释器能够搜索到的模块所有路径列表。在变量初始化时,默认包含了执行py的当前目录,PYTHONPATH环境变量,Python安装目录。当然,在程序中我们也可以动态的修改sys.path中的路径列表,解决无法导入模块的问题。
三 、 Python解释器是如何通过它来查找模块的?
这里先浅层的谈一下,,一般说来sys.path和sys.modules是搭配的,使用import …或是 from … import …, 编译程字节码,底层C语言执行函数时,会首先从sys.modules中查找模块是否已经被导入,如果存在则直接取,避免二次导入。如果不存在,依次搜索sys.path中的路径列表,去搜索目标模块,然后导入,导入之后,将对应的模块名和模块对象的映射添加到sys.modules中。
四 、 sys.path如何解决模块导入失败的问题?
注:该问题是基于通过命令行执行py产生。
假设目前,我们有一个项目,名为top, 项目下有两个模块,分别是sec和thr。
1 |
|
现在我想在模块下的base.py中导入thr模块下base.py。因此我这样写from thr import base
,在程序中这样导入,编译器不会报错。但是通过命令行python ./sec/base.py
来运行,就会产生错误ModuleNotFoundError: No module named 'thr'
,显示找不到包。
上述第二点中谈到的查找模块的过程是需要依赖sys.path和sys.modules。由于程序第一次运行,包并未被导入过,因此sys.modules中是找不到的,所以问题的原因就很明显了—–sys.path中找不到模块的路径,导致无法导包。
我们来看下通过命令行运行程序时的sys.path路径列表。
1 |
|
可以看出来第一个路径时当前正在执行的py的模块路径,其他路径是python安装路径。并没有thr模块的绝对路径以及top模块的绝对路径。
五 、解决方法:
为了解决这个问题,我们可以在程序中动态向sys.path添加总项目根目录的模块路径,使得thr可以被搜索到。
一般不同语言之间交互,会调用入口文件,我们也可以在入口文件中,向sys.path中总项目根目录的绝对路径。例如如下这样。
在项目根目录中添加一个main.py,在main.py添加如下代码。
1 |
|
六 、总结
要使得模块正常导入,要保证模块自身或上层所属的路径要存在与sys.path中,这样解释器根据sys.path就能够搜索到对应的模块,然后导入。
如果要调用的模块并不在sys.path中,应该手动向sys.path中追加模块路径。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!