模块和库

前面的练习中,我们的例子都是一个Python代码文件就实现了功能。

如果大家进入到企业里面,成为一名苦逼程序猿,就可以发现,项目开发的的代码文件,可能有成百上千个。

不同的代码文件,实现了不同的功能模块,就像一块块积木一样。这些功能模块文件最后合起来,实现了一个完整的软件。

所以,在Python中,一个代码文件代码,也就是一个.py文件,我们也叫它一个模块(Module)。

比如

a.py 文件,我们就可以称之为模块a

b.py 文件,我们就可以称之为模块b


模块之间的调用

那么模块之间是怎么互相联系的呢?

我们来看一个例子。

几个同事午餐经常一起去饭店聚餐,我们开发一个程序,记录每人的账单,月末可以结算

我们可以把记录到文件的功能实现在一个模块文件 aa.py, 其内容如下

fee = input('请输入午餐费用:')
members = input('请输入聚餐人姓名,以英文逗号,分隔:')

# 将人员放入一个列表
memberlist = members.split(',') 
# 得到人数
headcount = len(memberlist) 

# 计算人均费用
avgfee = int (fee) / headcount
print(avgfee)

好了,人均费用计算比较简单。

但是我们还需要将每次账单 记录到文件中,这样才好定期结算。

我们可以创建另外的一个模块文件 save.py。 在里面定义一个函数, 该函数实现记录消费信息到文件功能。 其内容如下

def savetofile(memberlist, avgfee):
    with open('record.txt','a',encoding='utf8') as f:
        # 通过列表生成式,产生    人:费用  这样的列表
        recordList = [f'{member}:{avgfee}' for member in memberlist]
        f.write(' | '.join(recordList) + '\n')
注意:目前我们把 save.py 和 aa.py 放在一个目录中

现在我们要在aa 模块里面使用save模块里面的函数 savetofile,该怎么做呢?

方法一

在aa.py里面 通过import关键字导入模块save ,

import save

这样save 就成了模块 aa 里面的的一个变量,这个变量指向的是一个 模块对象

不要感到奇怪,在Python中, 模块 也是一个对象。

这样我们就可以通过save.savetofile 访问到 save模块里面的函数

完整代码如下:

# 导入 save 模块 
# 导入后 save 就成为模块aa中的一个变量,对应一个模块对象
import save

fee = input('请输入午餐费用:')
members = input('请输入聚餐人姓名,以英文逗号,分隔:')

# 将人员放入一个列表
memberlist = members.split(',') 
# 得到人数
headcount = len(memberlist) 

# 计算人均费用
avgfee = int(fee) / headcount
print(avgfee)

# 使用 模块save里面的 savetofile 函数
save.savetofile(memberlist, avgfee)


方法二

还可以在 aa.py 里面 通过 from import 关键字导入其它模块里面的标识符(包括变量名和函数名等)。

导入之后,这些其它模块的变量名和函数名就成为 模块aa 里面 变量名,函数名了。

这样,我们就可以直接使用它们了。

完整代码如下:

# 从 save 模块 导入标识符  savetofile ,
# 导入后 savetofile 就成为模块aa中的一个变量,对应一个函数对象
from save import savetofile

fee = input('请输入午餐费用:')
members = input('请输入聚餐人姓名,以英文逗号,分隔:')

# 将人员放入一个列表
memberlist = members.split(',') 
# 得到人数
headcount = len(memberlist) 

# 计算人均费用
avgfee = fee / headcount
print(avgfee)

# 直接使用 savetofile 函数
savetofile(memberlist, avgfee) 


如果在一个模块文件中需要导多个其它模块,可以分开写导入语句,像这样

import aa
import bb
import cc

也可以一起导入,模块之间用逗号隔开,像这样

import aa, bb, cc

如果我们要从1个模块里导入多个标识符,可以这样

from aa import func1,var1,func2,var2

如果我们要导入1个模块里面的很多个标识符,可以使用*代表所有可导入的标识符(包括变量名,函数名等)

from aa import *

这里 import * 把aa模块所有可以导入的对象全部都导入了。


如果我们需要从两个模块导入函数,恰好这两个函数是同名的,这是我们可以给其中一个起个别名,避免冲突,比如

from save import savetofile
from save2 import savetofile as savetofile2


将模块放入包中

当我们的项目模块文件特别多的时候,我们还需要将这些模块文件根据功能划分到不同的目录中。

这些放模块文件的目录,Python中把他们称之为为包 (Package)。

包目录里面需要有一个名字为 __init__.py 的初始化文件,有了它,Python才认为这是一个Python包。

通常,这个初始化文件里面不需要什么代码,一个空文件就可以了。

当然你也可以在里面加入代码,当这个包里面的模块被导入的时候,这些代码就会执行。

下面是一个商城产品目录结构的例子(点击这里下载代码zip包)

stock/                        ---   顶层包
        __init__.py           ---   stock包的初始化文件
        food/                 ---   food子包
                __init__.py
                pork.py
                beef.py
                lobster.py
                ...
        furniture/            ---   furniture子包
                __init__.py
                bed.py
                desk.py
                chair.py
                ...
        kitchen/              ---   kitchen子包
                __init__.py
                knife.py
                pot.py
                bowl.py
                ...

最上层的是stock包, 里面有3个子包 food、furniture、kitchen。 每个子包里面的模块文件都有名为stockleft的函数,显示该货物还剩多少件。

如果我们要调用这些模块里面的函数,可以像这样:

import stock.food.beef
# 注意导入的是 stock.food.beef,调用的时候一定要加上所有的包路径前缀
stock.food.beef.stockleft()

我们也可以使用from…import… 的方式,像这样

from stock.food.beef import stockleft
stockleft()


库的概念

如果你写的 模块文件 里面的函数, 实现了通用的功能,经常被其它模块所调用, 我们就可以把这些被调用的模块文件称之为

库是个抽象的概念,里面提供被其它模块调用的功能函数(或者类等等)


Python标准库

Python语言提供了功能丰富的标准库 。 这些标准库把开发中常用的功能都做好了。

我们可以直接使用它们。

而这些标准库里面有一部分被称为内置库,这些库里面的 类型 和方法 无须使用import导入,可以直接使用。

内置类型有:int、float、str、list、tuple等


内置函数前面我们介绍过,可以在Python的官方文档查看到,点击这里查看

比如像 int,str,print,type,len等等




还有些库,需要使用import导入,才能使用。

常见有 sys, os, time, datetime, json等

比如,我们要结束Python程序,就可以使用sys库里面的exit函数

import sys
sys.exit(0)



再比如,我们要得到字符串形式的当前日期和时间,可以使用datetime库

import datetime

# 返回这样的格式 '20160423'
datetime.date.today().strftime("%Y%m%d") 

# 返回这样的格式 '20160423 19:37:36'
datetime.datetime.now().strftime("%Y%m%d %H:%M:%S")


解释器怎么寻找模块文件?

当我们用 import 或者 from … import来导入模块的时候, Python 解释器是怎么找到模块文件的?

有些标准库,内置在Python解释器程序中,不是磁盘上的模块文件,无需查找。

比如:time,sys等库

大家可以通过 sys.builtin_module_names的值来查看哪些模块是直接包含在解释器里面的。


除了这些,其余的模块,解释器是这样寻找的:

Python的 sys 库 里面有个变量 path。

这个 path 变量的值 是一个列表,这个列表里面包含了一些路径, 解释器就是依次到这些路径下面查找模块文件的。

大家可以运行下面的语句看看sys.path的内容

import sys
for path in sys.path:
    print (path)

通常可以得到类似下面这样的结果

C:\projects\first
C:\Python\Python36\python36.zip
C:\Python\Python36\DLLs
C:\Python\Python36\lib
C:\Python\Python36
C:\Python\Python36\lib\site-packages

就是说当我们import 一个模块时 ,解释器会 依次到上面列出的目录下去寻找。

其中第一个是启动脚本文件所在的目录 (启动脚本在不同的路径下面得到结果各不相同)

其余的是Python解释器的标准库目录,和安装的第三方库所在的目录(lib/site-packages)


如果我们自己想添加一些目录,作为模块搜索路径,怎么办呢?

一种方法是:把这些目录加到环境变量 PYTHONPATH 里。

因为Python解释器在启动后,会把 环境变量PYTHONPATH里包含的目录,自动添加到sys.path的路径列表里面。

比如,在windows下面,我们可以用这样的命令添加

set PYTHONPATH=c:\myproject;c:\myproject\mylib

那么解释器启动后, c:\myprojectc:\myproject\mylib 这两个目录就被添加到了sys.path里面。

注意这样的环境变量添加,只在当前命令行窗口有效。重新打开窗口就会失效了。

如果要确保持久有效,可以添加在windows 的 环境变量设置对话框中。

image


自己想添加一些目录,作为模块搜索路径,还有一种方法:

就是在代码中直接修改sys.path,使用 append或者insert方法,把目录直接添加到该列表中。


安装其他的库

Python 之所以这么流行,就是因为它有太多的优秀的第三方库和框架。

有了这些库,Python才能在各行各业都这么受欢迎。因为这些库极大的提高了开发效率。

要使用这些库,我们需要安装到本地。

在Python中,安装第三方库,通常是使用pip命令。

那些优秀的第三方库,基本都是放在一个叫 PYPI的网站上

pip命令会从该网站下载这些库的安装包进行安装。

例如,如果我们要安装 requests库,可以执行如下的命令

pip install requests 

注意,很多初学者会在python shell里面执行pip命令,像这样

image

这个命令是一个程序,不是Python语句,要在cmd 命令行中直接执行,像这样

image

安装好以后,我们就可以使用import去导入这些库并且使用了

import requests
requests.get('http://www.baidu.com')




课后练习

去做练习

上一页 下一页