python中模块查找的原理与方法详解


Posted in Python onAugust 11, 2017

前言

本文主要给大家介绍了关于python模块查找的原理与方式,分享出来供大家参考学习,下面话不多说,来一起看看详细的介绍:

基础概念

module

模块, 一个 py 文件或以其他文件形式存在的可被导入的就是一个模块

package

包,包含有 __init__ 文件的文件夹

relative path

相对路径,相对于某个目录的路径

absolute path

绝对路径,全路径

路径查找

python 解释器查找被引入的包或模块

Python 解释器是如何查找包和模块的

Python 执行一个 py 文件,无论执行的方式是用绝对路径还是相对路径,interpreter 都会把文件所在的 directory 加入 sys.path 这个 list 中,Python 就是在 sys.path 中查找包和模块的,sys.path 中的内容本身又是又 Python 的环境变量决定。

code-1

#test.py
import os
import sys
print sys.path[0]
# execute
python test.py
python /Users/x/workspace/blog-code/p2016_05_28_python_path_find/test.py

执行表明相对路径和绝对路径都输出相同的结果,而且无论哪种执行方式,test.py 所在的文件夹都会被加入 sys.path 的首位,也就是索引为0的位置。

Python 解释器查找包的顺序是什么

解释器查找包,首先搜索 built-in module,其次搜索 sys.path ,这样的查找顺序将会导致同名包或模块被遮蔽。

code-2

#ls
├── os.py
├── test2.py
├── redis.py
#test2.py
import os
from redis import Redis
#execute test2.py
Traceback (most recent call last):
 File "/Users/x/workspace/blog-code/p2016_05_28_python_path_find/test2.py", line 1, in <module>
 from redis import Redis
ImportError: cannot import name Redis

由于 os 是 built-in module,即使在同目录下有同名模块,解释器依然可以找到正确的 os 模块,可以证实 built-in module 不会被遮蔽,而 redis 属于第三方模块,默认安装位置是 Python 环境变量中的 site-packages,解释器启动之后会将此目录中的内容加入 sys.path,由于当前目录会在 sys.path 的首位,当前目录的 redis 优先被找到,site-packages 中的 redis 模块被遮蔽了。

交互式执行环境的查找顺序

进入交互式执行环境,解释器会自动把当前目录加入 sys.path, 这时当前目录是以相对路径的形式出现在 sys.path 中:

>>> import os.path
>>> import sys
>>> os.path.abspath(sys.path[0])
'/Users/x/workspace/blog-code'
>>>

除此之外,其他与执行一个文件是相同的。

模块中的 __file__ 变量

__file__ is the pathname of the file from which the module was loaded, if it was loaded from a file. 如果一个模块是从文件加载的,__file__ 就是该模块的路径名?Python Doc:

顾名思义,当模块以文件的形式出现 __file__ 指的是模块文件的路径名,以相对路径执行 __file__ 是相对路径,以绝对路径执行 __file__ 是绝对路径。

#test3.py
print __file__
#相对路径执行
python test3.py
test3.py
#绝对路径执行
python /Users/x/workspace/blog-code/p2016_05_28_python_path_find/test3.py
/Users/x/workspace/blog-code/p2016_05_28_python_path_find/test3.py

为了保证__file__ 每次都能准确得到模块的正确位置,最好对其再取一次绝对路径 os.path.abspath(__file__)

交互式 shell 中的 __file__

>>> __file__
Traceback (most recent call last):
 File "<input>", line 1, in <module>
NameError: name '__file__' is not defined

这是因为当前交互式shell的执行并不是以文件的形式加载,所以不存在__file__ 这样的属性。

sys.argv[0] 变量

sys.argv[0] 是它用来获取主入口执行文件。

#test.py
import sys
print __file__
print sys.argv[0]

以上 print 输出相同的结果,因为主执行文件和__file__所属的模块是同一个,当我们改变入口文件,区别就出现了。

#test.py
import sys
print __file__
print sys.argv[0]
#test2.py
import test
#execute test2.py
/Users/x/workspace/blog-code/p2016_05_28_python_path_find/child/test.py #__file__
test2.py #sys.argv[0]

总的来说,sys.argv[0] 是获得入口执行文件路径,__file__ 是获得任意模块文件的路径。

sys.modules 的作用

既然 Python 是在 sys.path 中搜索模块的,那载入的模块存放在何处?答案就是 sys.modules。模块一经载入,Python 会把这个模块加入 sys.modules 中供下次载入使用,这样可以加速模块的引入,起到缓存的作用。

>>> import sys
>>> sys.modules['tornado']
Traceback (most recent call last):
 File "<input>", line 1, in <module>
KeyError: 'tornado'
>>> import tornado
>>> sys.modules['tornado']
<module 'tornado' from '/Users/x/python_dev/lib/python2.7/site-packages/tornado/__init__.pyc'>

前面说过 Python 解释器启动之后,会把预先载入 built-in module,可以通过 sys.modules 验证。

>>> sys.modules['os']
<module 'os' from '/Users/x/python_dev/lib/python2.7/os.pyc'>
>>>

借助 sys.modules 和 __file__,可以动态获取所有已加载模块目录和路径。

>>> import os
>>> os.path.realpath(sys.modules['os'].__file__)
'/Users/x/python_dev/lib/python2.7/os.pyc'
>>> import tornado
>>> os.path.realpath(sys.modules['tornado'].__file__)
'/Users/x/python_dev/lib/python2.7/site-packages/tornado/__init__.pyc'
def get_module_dir(name):
 path = getattr(sys.modules[name], '__file__', None)
 if not path
 raise AttributeError('module %s has not attribute __file__'%name)
 return os.path.dirname(os.path.abspath(path))

summary

总的来说,Python 是通过查找 sys.path 来决定包的导入,并且系统包优先级>同目录>sys.path,Python 中的特有属性 __file__ 以及 sys.argv[0]sys.modules 都能帮助我们理解包的查找和导入概念,只要能正确理解 sys.path 的作用和行为,理解包的查找就不是难题了。

文中所有代码见:github

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Python 相关文章推荐
Python中文件遍历的两种方法
Jun 16 Python
python多线程操作实例
Nov 21 Python
Python中下划线的使用方法
Mar 27 Python
jupyter安装小结
Mar 13 Python
Python使用matplotlib绘图无法显示中文问题的解决方法
Mar 14 Python
解决python3 安装完Pycurl在import pycurl时报错的问题
Oct 15 Python
Python单元测试unittest的具体使用示例
Dec 17 Python
使用Python调取任意数字资产钱包余额功能
Aug 15 Python
python采集百度搜索结果带有特定URL的链接代码实例
Aug 30 Python
Django Path转换器自定义及正则代码实例
May 29 Python
浅谈Python 命令行参数argparse写入图片路径操作
Jul 12 Python
Selenium执行完毕未关闭chromedriver/geckodriver进程的解决办法(java版+python版)
Dec 07 Python
python利用lxml读写xml格式的文件
Aug 10 #Python
Python编程实现及时获取新邮件的方法示例
Aug 10 #Python
Python中函数eval和ast.literal_eval的区别详解
Aug 10 #Python
Python基础之getpass模块详细介绍
Aug 10 #Python
Python中字典(dict)合并的四种方法总结
Aug 10 #Python
详解Python 模拟实现生产者消费者模式的实例
Aug 10 #Python
Python 操作文件的基本方法总结
Aug 10 #Python
You might like
DEDECMS首页调用图片集里的多张图片
2015/06/05 PHP
PHP实现HTTP断点续传的方法
2015/06/17 PHP
Yii框架参数化查询中IN查询只能查询一个的解决方法
2017/05/20 PHP
PHP实现图片压缩
2020/09/09 PHP
php操作redis常见方法示例【key与value操作】
2020/04/14 PHP
js编写trim()函数及正则表达式的运用
2013/10/24 Javascript
使用GruntJS构建Web程序之合并压缩篇
2014/06/06 Javascript
常用的jquery模板插件——jQuery Boilerplate介绍
2014/09/23 Javascript
jQuery.trim() 函数及trim()用法详解
2015/10/26 Javascript
vue2.0开发实践总结之入门篇
2016/12/06 Javascript
nodejs个人博客开发第一步 准备工作
2017/04/12 NodeJs
关于JavaScript中forEach和each用法浅析
2017/07/27 Javascript
详解Angular2表单-模板驱动的表单(Template-Driven Forms)
2017/08/04 Javascript
angular6.0开发教程之如何安装angular6.0框架
2018/06/29 Javascript
vue2中使用sass并配置全局的sass样式变量的方法
2018/09/04 Javascript
vue+Element-ui实现登录注册表单
2020/11/17 Javascript
CentOS7.3编译安装Python3.6.2的方法
2018/01/22 Python
python中不能连接超时的问题及解决方法
2018/06/10 Python
python操作excel文件并输出txt文件的实例
2018/07/10 Python
对python借助百度云API对评论进行观点抽取的方法详解
2019/02/21 Python
Python算法中的时间复杂度问题
2019/11/19 Python
Django 解决上传文件时,request.FILES为空的问题
2020/05/20 Python
Opencv求取连通区域重心实例
2020/06/04 Python
Python eval函数介绍及用法
2020/11/09 Python
python 如何停止一个死循环的线程
2020/11/24 Python
澳大利亚拥有最佳跳伞降落点和最好服务的跳伞项目运营商:Skydive Australia
2018/03/05 全球购物
集团公司总经理岗位职责
2013/12/20 职场文书
财务部总监岗位职责
2014/03/12 职场文书
党员一句话承诺大全
2014/03/28 职场文书
商场开业庆典策划方案
2014/06/02 职场文书
质量月活动总结
2014/08/26 职场文书
部队反四风对照检查材料
2014/09/26 职场文书
党员反对四风思想汇报范文
2014/10/25 职场文书
普宁寺导游词
2015/02/04 职场文书
物业工程部主管岗位职责
2015/04/16 职场文书
使用canvas实现雪花飘动效果的示例代码
2021/03/30 HTML / CSS