学习目标:
了解Python中模块和包的概念,掌握相关包和模块的导入和使用方法
模块是一个包含所有你定义的函数和变量的文件,其后缀名是.py
。模块可以被别的程序引入,以使用该模块中的函数等功能。这也是使用 python 标准库的方法。
假设你写了一个10000行代码的程序,如果把全部代码写在一个文件里,查询起来将会非常困难。每次出现错误或异常时,不得不快速浏览10000行代码来查找导致问题的那行。为解决这个问题,程序员将大型程序分割成多个包含Python代码的文件,也就是被称为模块(Module)。Python支持在一个模块中使用另一个模块内的代码,也有内置模块,它是Python语言自带的,包含了许多重要的功能。本节将学习模块及其使用方式。
一、模块的概念
模块就是一个工具包,这个工具包(模块
)对外提供全局变量、函数、类三种类型的工具,工具包名称(模块名
)实则是一个标识符,需要满足标识符命名规范,而模块的本质就是以.py
为扩展名的源代码文件。
模块的开发原则也很简单,就是每一个文件应该是可以被导入的,我们可以理解为:
模块中所有没有任何缩进的代码都应该被执行一遍,加载到内存,以供调用者使用;
模块中的测试代码应该保证仅在其内部使用,而被导入到其他文件中应该不被执行;
这么一看,那么问题来了,我们该如何让测试代码满足以上的执行条件呢?接下来我们需要学习一下python中的一个内置属性__name_,此属性记录着一个字符串,详情如下表:
分情况讨论 name值 模块为当前执行程序时 __main__
(双下划线字符串)模块被其他文件导入时 被导入 模块名
由此,我们可以好好使用这个属性,将我们的测试代码放入其中,如下:
1 | if __name__ = "__main__": |
这样,我们的测试代码仅在模块为当前执行程序时,被导入将不再执行,大功告成!最后,给出推荐的模块代码格式,如下:
1 | # 导入模块 |
模块的作用总结起来有三点:
提高代码重用性
系统命名空间的划分
实现共享服务和数据
模块分为三种:
内置模块
第三方模块
自定义模块
模块导入规范
- 文件头部导入
- 内置模块放在最开始
- 第三方模块放在中间
- 自定义模块放在最后
- 不同种类模块之间空一行
二、包的概念
包是一种管理 Python 模块命名空间的形式,采用”点模块名称”。比如一个模块的名称是 A.B, 那么他表示一个包 A中的子模块 B 。就好像使用模块的时候,你不用担心不同模块之间的全局变量相互影响一样,采用点模块名称这种形式也不用担心不同库之间的模块重名的情况。这样不同的作者都可以提供 NumPy 模块,或者是 Python 图形库。不妨假设你想设计一套统一处理声音文件和数据的模块(或者称之为一个”包”)。现存很多种不同的音频文件格式(基本上都是通过后缀名区分的,例如: .wav,:file:.aiff,:file:.au,),所以你需要有一组不断增加的模块,用来在不同的格式之间转换。并且针对这些音频数据,还有很多不同的操作(比如混音,添加回声,增加均衡器功能,创建人造立体声效果),所以你还需要一组怎么也写不完的模块来处理这些操作。这里给出了一种可能的包结构(在分层的文件系统中):
1 | sound/ #顶层包 |
在导入一个包的时候,Python 会根据 sys.path
中的目录来寻找这个包中包含的子目录。
目录只有包含一个叫做 __init__
.py
的文件才会被认作是一个包,主要是为了避免一些滥俗的名字(比如叫做 string)不小心的影响搜索路径中的有效模块。
最简单的情况,放一个空的 :file:__init__
.py
就可以了。当然这个文件中也可以包含一些初始化代码或者为(将在后面介绍的) all变量赋值。
用户可以每次只导入一个包里面的特定模块,比如:
1 | import sound.effects.echo |
这将会导入子模块:sound
.effects
.echo
。 他必须使用全名去访问:
1 | sound.effects.echo.echofilter(input, output, delay=0.7, atten=4) |
还有一种导入子模块的方法是:
1 | from sound.effects import echo |
这同样会导入子模块: echo,并且他不需要那些冗长的前缀,所以他可以这样使用:
1 | echo.echofilter(input, output, delay=0.7, atten=4) |
还有一种变化就是直接导入一个函数或者变量:
1 | from sound.effects.echo import echofilter |
同样的,这种方法会导入子模块: echo,并且可以直接使用他的 echofilter()
函数:
1 | echofilter(input, output, delay=0.7, atten=4) |
注意当使用 from package import item 这种形式的时候,对应的 item 既可以是包里面的子模块(子包),或者包里面定义的其他名称,比如函数,类或者变量。
import 语法会首先把 item 当作一个包定义的名称,如果没找到,再试图按照一个模块去导入。如果还没找到,抛出一个 :exc:ImportError
异常。
反之,如果使用形如 import item.subitem.subsubitem
这种导入形式,除了最后一项,都必须是包,而最后一项则可以是模块或者是包,但是不可以是类,函数或者变量的名字。
模块:一个包含所有你定义的函数和变量的文件,其后缀名是
.py
,一个.py
文件就是一个模块包:一个包含
__init__
.py
模块 的文件夹,一般也会包含其他一些模块和子包库(lib):库是完成一定功能的代码集合,具体表现可以是包,也可以是一个模块
框架(framework):为解决一个开放性问题而设计的具有一定约束性的支撑结构
python内置了一些库,除此之外,还有其他人自己做的一些库,称之为第三方库
一般把第三方库放在…/python3/lib/site_packages中
三、模块和包的导入
使用模块之前,必须先导入(import):意味着要写代码,以便让Python知道从哪获取模块。Python导入模块有以下几种方式:
1 | import module |
导入示例如下:
1 | import math |
导入模块其实就是告诉Python解释器去解释哪个py
文件
- 导入一个
py
文件,解释器解释该py
文件 - 导入一个包,解释器解释该包下的
__init__
.py
文件
模糊导入中的*中的模块是由__all__
来定义的,__init__
.py
的另外一个作用就是定义package中的__all__
,用来模糊导入,如__init__
.py
:
__init__
.py
控制着包的导入行为。假如 __init__
.py
为空,那么仅仅导入包是什么都做不了的。
1 | from dingxiangyuan import * # 虽然dingxiangyuan文件夹下有DBHelper模块 但没有定义__all__ |
定义变量all
1 | __all__ = ['DBHelper'] |
包外调用
1 | from dingxiangyuan import * |
从上边的例子可以看出,init.py的主要作用是:
- Python中package的标识,不能删除
- 定义all用来模糊导入
- 编写Python代码(不建议在init中写python模块,可以在包中在创建另外的模块来写,尽量保证init.py简单)
那么问题来了,导入模块时是根据那个路径作为基准来进行的呢?即:sys.path
1 | import sys |
搜索规则:
- 搜索
当前目录
,若模块名存在,则直接导入,否则继续搜索; - 搜索
系统目录
,若模块名存在,则直接导入,否则调用模块中的方法时,将会抛出异常;
如果sys.path
路径列表没有你想要的路径,可以通过 sys.path.append('路径')
添加。
例如:将当前文件的目录的上一层目录添加到环境路径中。
1 | import os,sys |
dir() 函数
内置的函数 dir() 可以找到模块内定义的所有名称。以一个字符串列表的形式返回:
1 | import os |
如果没有给定参数,那么 dir()
函数会罗列出当前定义的所有名称:
1 | dir() |
四、第三方模块
安装第三方库实质上是下载并使用别人写的代码。常见的第三方库的格式:源码(Source)(压缩包,需先解压,得到包含setup.py文件夹);egg(本质是压缩包);whl
(本质也是压缩文件)。
1. 下载和安装
源码安装(本地安装):手动下载,再安装到本地;
(1)到对应库托管网站下载所需要的文件,https://pypi.org/或https://www.lfd.uci.edu/~gohlke/pythonlibs/等
(2)下载的文件要对应自己python的版本,还要选择32位还是64位安装的python的系统
(3)打开命令行(win+R cmd):切换到下载的文件所在的目录 cd /d
(4)对于带setup.py的文件(源码文件),输入命令:python setup.py install。注意:若没有
setuptools
包,需手动下载安装,再利用setuptools
安装其他使用setuptools
打包的包(5)对于 .egg文件使用easy_stall安装,输入命令:easy_install xxx.egg(完整文件名称)
(6)对于
whl
文件可以使用easy_stall如上安装,也可以使用pip安装,输入命令:pip install xxx.whl(完整文件名称)
包管理安装(远程安装):通过命令使自动化的为用户安装管理包和模块。安装命令如下:
1
yum(linux),pip,apt-get(linux)
使用国内源安装
(1)默认pip是使用Python官方的源,但是由于国外官方源经常被墙,导致不可用,我们可以使用国内的python镜像源,从而解决Python安装不上库的烦恼。国内有很多源,比如:
1
2
3
4
5(1)阿里云 http://mirrors.aliyun.com/pypi/simple/
(2)豆瓣http://pypi.douban.com/simple/
(3)清华大学 https://pypi.tuna.tsinghua.edu.cn/simple/
(4)中国科学技术大学 http://pypi.mirrors.ustc.edu.cn/simple/
(5)华中科技大学http://pypi.hustunique.com/(2)临时使用
1
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple 模块名
(3)永久修改,一劳永逸
1
2
3
4
5
6
7
8
9
10
11Linux下,修改 ~/.pip/pip.conf (没有就创建一个), 修改 index-url至tuna,内容如下:
[global]
index-url = http://mirrors.aliyun.com/pypi/simple/
[install]
trusted-host=mirrors.aliyun.com
windows下,直接在user目录中创建一个pip目录,如:C:\Users\xx\pip,新建文件pip.ini,内容如下:
[global]
index-url = http://mirrors.aliyun.com/pypi/simple/
[install]
trusted-host=mirrors.aliyun.com
2. 卸载
1 | pip uninstall 模块名 |
3. 更新pip
若提示更新pip
1 | WARNING: You are using pip version 20.2.3; however, version 20.2.4 is available. |
按提示输入 python -m pip install –upgrade pip,还是报错
1 | ValueError: Unable to find resource t64.exe in package pip._vendor.distlib |
解决方法
1 | python -m pip uninstall pip setuptools |
五、内置模块
官网网址:https://docs.python.org/3/py-modindex.html
关于内置模块,也称标准库模块,我们将再另一章节讲解。