前言
在python的模块有两种组织方式,一种是单纯的python文件,文件名就是模块名,一种是包,包是一个包含了若干python文件的目录,目录下必须有一个文件__init__.py,这样目录名字就是模块名,包里的python文件也可以通过包名.文件名的方式import
import语法
import语法有两种
1、直接import模块
import Module import Module as xx
2、从模块import对象(下级模块,类,函数,变量等)
from Module import Name from Module immport Name as yy
as语法是用来设置对象(这里用对象泛指模块,类,函数等等)别名,import将对象名字引入了当前文件的名字空间
假设有如下目录结构
├── A.py └── pkg ├── B.py └── __init__.py
在当前目录下,以下语句都是有效的
import A import pkg import pkg.B from pkg import B
为了简化讨论,下面将不会对as语法进行举例
import步骤
python所有加载的模块信息都存放在sys.modules结构中,当import一个模块时,会按如下步骤来进行
嵌套import
在import模块时我们可能会担心一个模块会不会被import多次,假设有A,B,C三个模块,A需要import B和C,B又要import C,这样A会执行到两次import C,一次是自己本身import,一次是在import B时执行的import,但根据上面讲到的import步骤,在第二次import时发现模块已经被加载,所以不会重复import
但如下情况却会报错
#filename: A.py from B import BB class AA:pass #filename: B.py from A import AA class BB:pass
这时不管是执行A.py还是B.py都会抛出ImportError的异常,假设我们执行的是A.py,究其原因如下
解决这种情况有两种办法,
总之,import需要注意的是,尽量在需要用到时再import
包的import
当一个目录下有__init__.py文件时,该目录就是一个python的包
import包和import单个文件是一样的,我们可以这样类比:
假设有如下目录结构
pkg ├── __init__.py └── file.py
其中__init__.py内容如下
argument = 0 class A:pass
在和pkg同级目录下执行如下语句都是OK的
>>> import pkg >>> import pkg.file >>> from pkg import file >>> from pkg import A >>> from pkg import argument
但如下语句是错误的
>>> import pkg.A >>> import pkg.argument
报错ImportError: No module named xxx,因为当我们执行import A.B,A和B都必须是模块(文件或包)
相对导入和绝对导入
绝对导入的格式为import A.B或from A import B,相对导入格式为from . import B或from ..A import B,.代表当前模块,..代表上层模块,...代表上上层模块,依次类推。当我们有多个包时,就可能有需求从一个包import另一个包的内容,这就会产生绝对导入,而这也往往是最容易发生错误的时候,还是以具体例子来说明
目录结构如下
app ├── __inti__.py ├── mod1 │ ├── file1.py │ └── __init__.py ├── mod2 │ ├── file2.py │ └── __init__.py └── start.py
其中app/start.py内容为import mod1.file1
app/mod1/file1.py内容为from ..mod2 import file2
为了便于分析,我们在所有py文件(包括__init__.py)第一行加入print __file__, __name__
现在app/mod1/file1.py里用到了相对导入,我们在app/mod1下执行python file1.py或者在app下执行python mod1/file1.py都会报错ValueError: Attempted relative import in non-package
在app下执行python -m mod1.file1或python start.py都会报错ValueError: Attempted relative import beyond toplevel package
具体原因后面再说,我们先来看一下导入模块时的一些规则
在没有明确指定包结构的情况下,python是根据__name__来决定一个模块在包中的结构的,如果是__main__则它本身是顶层模块,没有包结构,如果是A.B.C结构,那么顶层模块是A。
基本上遵循这样的原则
有目录结构如下
A ├── B1 │ ├── C1 │ │ └── file.py │ └── C2 └── B2
其中A,B1,B2,C1,C2都为包,这里为了展示简单没有列出__init__.py文件,当file.py的包结构为A.B1.C1.file(注意,是根据__name__来的,而不是磁盘的目录结构,在不同目录下执行file.py时对应的包目录结构都是不一样的)时,在file.py中可采用如下的绝对的导入
import A.B1.C2 import A.B2
和如下的相对导入
from .. import C2 from ... import B2
什么情况下会让file.py的包结构为A.B1.C1.file呢,有如下两种
再看前面出错的两种情况,第一种执行python file1.py和python mod1/file1.py,此时file.py的__name__为__main__ ,也就是说它本身就是顶层模块,并没有包结构,所以会报错
第二种情况,在执行python -m mod1.file1和python start.py时,前者明确告诉解释器mod1是顶层模块,后者需要导入file1,而file1.py的__name__为mod1.file1,顶层模块为也mod1,所以在file1.py中执行from ..mod2 import file2时会报错 ,因为mod2并不在顶层模块mod1内部。通过错误堆栈可以看出,并不是在start.py中绝对导入时报错,而是在file1.py中相对导入报的错
那么如何才能偶正确执行呢,有两种方法,一种是在app上层目录执行python -m app.mod1.file1,另一种是改变目录结构,将所有包放在一个大包中,如下
app ├── pkg │ ├── __init__.py │ ├── mod1 │ │ ├── __init__.py │ │ └── file1.py │ └── mod2 │ ├── __init__.py │ └── file2.py └── start.py
start.py内容改成import pkg.mod1.file1,然后在app下执行python start.py
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家学习或者使用python能带来一定的帮助,如有疑问大家可以留言交流。
Python 中第一个让人印象深刻的语法就是缩进,Python 跟 js 不同,跟golang 不同,跟 shell script 不同,跟 c 不同,它们并没有要求必须缩进,但是 Python 不同,它就如同 jade 一样,缩进是必须的。
本文向大家介绍Python中的类学习笔记,包括了Python中的类学习笔记的使用技巧和注意事项,需要的朋友参考一下 Python使用中面向对象的语言,支持继承、多态; 定义一个Person类: 可以修改Person的类方法 Person().sayHello也是一个函数,可以赋值给变量,并可以直接调用; Person.sayHello与Person().sayhello并不是同一个对象,直
本文向大家介绍Python异常学习笔记,包括了Python异常学习笔记的使用技巧和注意事项,需要的朋友参考一下 异常(exceptions)是Python中一种非常重要的类型,它和语法错误不同,是在程序运行期间引发的错误。Python中内置了很多异常,如IOError,NameError,KeyboardInterrupt等,更多的异常可以点击这里。 异常的意义在于提供一种更加优雅的运行方式,例如
本文向大家介绍python web框架学习笔记,包括了python web框架学习笔记的使用技巧和注意事项,需要的朋友参考一下 一、web框架本质 1.基于socket,自己处理请求 2.基于wsgi WSGI,全称 Web Server Gateway Interface,或者 Python Web Server Gateway Interface ,是为 Python 语言定义的 Web 服务
问题内容: 我刚开始使用Python,却不知道什么是记忆以及如何使用它。另外,我可以举一个简化的例子吗? 问题答案: 记忆有效地指基于方法输入记忆方法调用的结果(“记忆”→“备忘录”→要记忆),然后返回记忆的结果,而不是再次计算结果。你可以将其视为方法结果的缓存。有关更多详细信息,请参见第387页的Cormen等人的《算法简介》(3e)中的定义。 一个简单的示例,使用Python中的记忆来计算阶乘
本文向大家介绍python学生管理系统学习笔记,包括了python学生管理系统学习笔记的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了python学生管理系统的具体代码,供大家参考,具体内容如下 基于列表存储的学生管理系统,实现如下功能 ================== 学生管理系统 1、添加学生信息 2、删除学生信息 3、查询学生信息 4、修改学生信息 5、显示所有学生信息 6