解析Python3中的Import


Posted in Python onOctober 13, 2019

Python import的搜索路径

import的搜索路径为:

  • 搜索「内置模块」(built-in module)
  • 搜索 sys.path 中的路径
  • 而sys.path在初始化时,又会按照顺序添加以下路径:

foo.py 所在目录(如果是软链接,那么是真正的 foo.py 所在目录)或当前目录;

环境变量 PYTHONPATH中列出的目录(类似环境变量 PATH,由用户定义,默认为空);
site 模块被 import 时添加的路径1(site 会在运行时被自动 import)。

import site 所添加的路径一般是 XXX/site-packages。如果懒得记 sys.path 的初始化过程,可以简单的认为 import 的查找顺序是:

内置模块

.py 文件所在目录
pip 或 easy_install 安装的包

绝对导入和相对导入

绝对导入和相对导入的关系可以类比绝对路径和相对路径。

绝对导入的格式为:

import A.B
或
from A import B

相对导入格式为:

from . import B
或
from ..A import B

其中,点号.代表当前模块,..代表上层模块,…代表上上层模块,依次类推。

模块的执行方式

模块的执行可以有两种方式:直接执行和以模块执行,即:

python example/foo.py
或
python -m example.foo

注意,以模块执行时,一定要有包的概念,即example一定是个包,而foo是这个包下的模块,这样才能顺利执行。

包和模块

模块: 一个 .py 文件就是一个模块(module)

包: init .py 文件所在目录就是包(package)

各种情形测试

模块直接导入

即模块所在的目录都不是一个包结构,各个模块都是独立的,比如以下的目录结构:

D:\LEARN\IMPORT_TEST\TEST1
├─pack1
│  modu1.py
└─pack2
  modu2.py

modu1.py中的内容为:

import sys
sys.path.append("D:\\learn\\import_test\\TEST1\\pack2")
from modu2 import hello2
hello2()

modu2.py中的内容为:

def hello2():
 print("hello, I am module 2")

注意在modu1中一定加上sys.path.append那部分内容,即根据上面的描述,一定要让modu1能找到modu2才行,否则就会出现如下错误:

ModuleNotFoundError: No module named 'modu2'

此时进入pack1目录下,以直接执行或模块执行的方式都可以顺利输出。

包外导入

将上面两个模块所在的目录都变为包结构,即:

D:\LEARN\IMPORT_TEST\TEST2
├─pack1
│  modu1.py
│  __init__.py
└─pack2
  modu2.py
  __init__.py

此时也能顺利执行,同时比上面非包结构的多出来一条执行方式,即:

python -m pack1.modu1

即以包名+模块名的方式执行。

上面两种情形,即模块与模块、包与包都是相互独立的关系,也就没有相对导入的意义。

如果是在一个包内的不同模块的导入,那么最自然的就是使用相对导入。

包内相对导入

D:\LEARN\IMPORT_TEST\Test3
│ __init__.py
│
├─pack1
│  modu1.py
│  __init__.py
│
└─pack2
  modu2.py
  __init__.py

此时modu1.py中的内容为:

from ..pack2.modu2 import hello2
hello2()

即将sys.path.append去掉,因为是在一个包内相互引用,此时这样写没有意义。

此时正确运行的方式是进入Test3上一层的文件夹,然后:

python -m Test3.pack1.modu1

即明确地告诉解释器模块的层次结构。

而如果采用直接运行的方式,比如:

python Test3\pack1\modu1.py

就会报如下错误:

ValueError: attempted relative import beyond top-level package

这是因为,相对导入使用模块的 name (这里的name和下面的main都是有两个下划线的,但是网页显示不出来。。)属性来决定模块在包结构中的位置。当 name 属性不包含包信息(i.e. 没有用'.'表示的层次结构,比如' main ‘),则相对导入将模块解析为顶层模块,而不管模块在文件系统中的实际位置。这里模块被直接运行,则它自己为顶层模块,不存在层次结构,所以找不到其他的相对路径。

因此,直接运行带有相对导入的模块是不行的,需要通过模块运行的方式,将包结构明确告诉它才行。

这个原理也适用于下面这种错误,比如将modu2移动到pack1中,即与modu1在同一个目录下,然后将modu1的内容改为这样的相对引用:

from .modu2 import hello2
hello2()

此时使用模块执行的方式没有问题,如果还是想尝试直接运行,那么就会出现:

ModuleNotFoundError: No module named '__main__.modu2'; '__main__' is not a package

原因就是此时没有包结构, main 也不是个包。

那么解决方法就是或者使用模块运行的方式运行,或者将它改成下面的绝对导入的方式就可以直接运行。

包内绝对导入

那么,如果将modu1.py中的内容改为绝对导入,即:

from Test3.pack2.modu2 import hello2
hello2()

此时正确运行方式也是进入Test3上一层文件夹,然后使用模块执行的方式运行:

python -m Test3.pack1.modu1

如果此时采用直接运行的方式:

python Test3\pack1\modu1.py

那么就会报错:

ModuleNotFoundError: No module named 'Test3'

这主要是因为Test3没有被找到,即按照第一部分所说,Test3没有在import的搜索路径中。所以,只要将它加入进去即可,比如:

set PYTHONPATH=D:\learn\import_test\

此时再直接运行就没有问题了。

总结

以上所述是小编给大家介绍的Python3中的Import理解,希望对大家有所帮助!

Python 相关文章推荐
python抓取某汽车网数据解析html存入excel示例
Dec 04 Python
Python中的自定义函数学习笔记
Sep 23 Python
Python入门篇之文件
Oct 20 Python
Django学习笔记之Class-Based-View
Feb 15 Python
python增加矩阵维度的实例讲解
Apr 04 Python
对Python的zip函数妙用,旋转矩阵详解
Dec 13 Python
Django中reverse反转并且传递参数的方法
Aug 06 Python
django formset实现数据表的批量操作的示例代码
Dec 06 Python
opencv-python 读取图像并转换颜色空间实例
Dec 09 Python
Django 路由层URLconf的实现
Dec 30 Python
Python如何实现FTP功能
May 28 Python
calendar在python3时间中常用函数举例详解
Nov 18 Python
Python英文文章词频统计(14份剑桥真题词频统计)
Oct 13 #Python
Python 转换RGB颜色值的示例代码
Oct 13 #Python
Django中自定义查询对象的具体使用
Oct 13 #Python
PyCharm导入python项目并配置虚拟环境的教程详解
Oct 13 #Python
Python 用三行代码提取PDF表格数据
Oct 13 #Python
Python3离线安装Requests模块问题
Oct 13 #Python
详解使用Python下载文件的几种方法
Oct 13 #Python
You might like
Yii框架实现邮箱激活的方法【数字签名】
2016/10/18 PHP
php两点地理坐标距离的计算方法
2018/12/29 PHP
laravel 实现划分admin和home 模块分组
2019/10/15 PHP
PHP 文件写入和读取操作实例详解【必看篇】
2019/11/04 PHP
JS 用6N±1法求素数 实例教程
2009/10/20 Javascript
在IE 浏览器中使用 jquery的fadeIn() 效果 英文字符字体加粗
2011/06/02 Javascript
关于js注册事件的常用方法
2013/04/03 Javascript
Js制作简单弹出层DIV在页面居中 中间显示遮罩的具体方法
2013/08/08 Javascript
常用的JS验证和函数汇总
2014/12/23 Javascript
获取阴历(农历)和当前日期的js代码
2016/02/15 Javascript
AngularJS HTML DOM详解及示例代码
2016/08/17 Javascript
基于JavaScript实现本地图片预览
2017/02/08 Javascript
vue cli webpack中使用sass的方法
2018/02/24 Javascript
javascript、php关键字搜索函数的使用方法
2018/05/29 Javascript
微信小程序学习笔记之函数定义、页面渲染图文详解
2019/03/28 Javascript
Python中非常实用的一些功能和函数分享
2015/02/14 Python
各个系统下的Python解释器相关安装方法
2015/10/12 Python
python解决汉字编码问题:Unicode Decode Error
2017/01/19 Python
python 容器总结整理
2017/04/04 Python
pip matplotlib报错equired packages can not be built解决
2018/01/06 Python
Python实现动态图解析、合成与倒放
2018/01/18 Python
使用Python实现将list中的每一项的首字母大写
2019/06/11 Python
matplotlib命令与格式之tick坐标轴日期格式(设置日期主副刻度)
2019/08/06 Python
Python生成器实现简单"生产者消费者"模型代码实例
2020/03/27 Python
python 使用paramiko模块进行封装,远程操作linux主机的示例代码
2020/12/03 Python
CSS3 icon font完全指南(CSS3 font 会取代icon图标)
2013/01/06 HTML / CSS
css3 transform及原生js实现鼠标拖动3D立方体旋转
2016/06/20 HTML / CSS
Javascript 高级手势使用介绍
2013/04/21 HTML / CSS
AE美国鹰美国官方网站:American Eagle Outfitters
2016/08/22 全球购物
英国现代家具和装饰网站:PN Home
2018/08/16 全球购物
介绍一下linux文件系统分配策略
2013/02/25 面试题
飞利信loadrunner和软件测试笔试题
2012/09/22 面试题
成绩单家长评语大全
2014/04/16 职场文书
师范毕业生求职信
2014/07/11 职场文书
党支部三严三实对照检查材料思想汇报
2014/09/29 职场文书
2014年教研员工作总结
2014/12/23 职场文书