模块和包

1,认识模块

为了编写可维护的代码,需要把很多个类和函数进行分组,分门别类地放到不同的文件里这样每个文件的代码就相对减少了,维护起来也变得轻松。

在python中,一个以.py为扩展名的文件就叫做一个模块(Module),每一个模块在Python里都是一个独立的文件。模块可以包含直接运行的代码、类定义、函数定义等任何Python源代码。模块可以被其他模块、脚本、甚至是交互解析器导入(import)使用,也可以被其他程序引用。导入的源代码会直接被解析运行。

使用模块的好处:

1
2
3
#提高代码的可维护性
#提高代码的可重用性
#避免命名冲突,避免代码污染

Python模块可以分为3种类型

1
2
3
#内置标准模块,又称为标准库,如sys、time、json模块等
#第三方开源代码:这类模块可以通过"pip install 模块名"进行在线安装。如果pip安装命令失败,也可以直接访问模块所在官网下载安装包,在本地离线安装。
#自定义模块:由开发者自己开发的模型,方便在其他程序或脚本中使用。

【提示】:

1
Python模块一般都位于安装目录下Lib文件中,执行help("modules")命令,可以查看已经安装的所有模块列表。
1
自定义模块的名称不能与系统模块重名,否则有覆盖掉内置模块的风险。例如:自定义一个sys.py模块后,就不能再使用系统的sys模块。

2,使用模块

Python内置了很多非常有用的模块,只要成功安装Pyhthon,就可以使用。

1,导入模块

使用import语句导入模块,语法格式如下:

1
import module1[,module2[...,moduleN]]

import 关键字后面是一组模块的列表,多个模块之间使用逗号分隔。module1、module2和moduleN等表示模块名称,即Python文件名,模块名称不包括.py扩展名。

当python解释器在源代码中解析到import关键字时,会自动在搜索路径中搜寻对应的模块,如果发现就会立即导入。

【提示】

1
搜索路径是一个目录列表,供Python解释器在导入模块时进行参考,可以事先配置,或者在源代码中设置。

【示例1】本示例用import语句从Python标准库中导入sys模块

1
2
3
4
import sys

for i in sys.modules:
print(i,end="、")

sys是Python的内置模块,当执行import sys命令后,Python在sys.path变量所列目录中寻找sys模块文件的路径。导入成功,会运行这个模块的源代码并进行初始化,然后就可以使用该模块了。

​ 导入sys模块之后,可以使用dir(sys)方法查看该模块中可用的成员。sys.modules是一个字典对象,每当导入新的模块,sys.modules会自动记录该模块。

【提示】:

1
一般建议import命令放在脚本文档的顶端。在一个文档中,不管执行了多少钱次import命令,一个模块仅导入一次,这样可以防止滥用import命令。

访问模块中的变量,函数、类对象时,可以使用点语法,在变量名,函数名和类名前面添加模块前缀,如sys.modules、sys.argv(命令),sys.path(搜索路径列表)等。

如果模块名比较长,在导入模块时可以给他另起一个别名,语法格式如下:

1
import modules as 模块名

在导入模块语句的后面添加as关键字,设置一个简单、好记的别名。然后,在脚本中就可以使用别名来访问模块内的变量、函数和类等对象。

【示例2】本示例使用import命令导入random模块,设置一个别名r,然后就可以使用r访问该模块中的randint()函数,随机生成10个0-10之间的随机数。

1
2
3
import random as r
for i in range(10):
print(r.randint(1,10),end=" ")

2,搜索路径

搜索路径类似环境变量,它由一系列目录名组成,Python解释器能够依次从这些目录中去寻找所要的导入的模块。

搜索路径是在Python编译或安装的时候确定的,安装新的库应该也会修改。搜索路径被存储在sys模块的path变量中。例如,在交互式命令行中输入;

1
2
import sys
sys.path

输出为:

1
['', 'D:\\python\\python310.zip', 'D:\\python\\DLLs', 'D:\\python\\lib', 'D:\\python', 'D:\\python\\lib\\site-packages']

sys.path输出一个列表,如果第一项是空字符串’ ‘,则表示当前目录,即执行python解释器的目录,对于脚本来说就是运行脚本所在的目录。如果第一项不是空字符串,则它也表示完整的当前目录。

一般python会按如下顺序搜索模块。

1
2
3
第1步,当前目录。
第2步,PTHONPATH(环境变量)下的每个目录。
第3步,Python安装目录。

手动添加搜索路径有3种方法,具体说明如下:

1,临时添加

可以直接在脚本中为sys.path列表添加目录项。例如:

1
2
3
import sys 
sys.path.append("E:/path/")
print(sys.path)
1
['', 'D:\\python\\python310.zip', 'D:\\python\\DLLs', 'D:\\python\\lib', 'D:\\python', 'D:\\python\\lib\\site-packages','E:/path/']

这样就可以在列表的尾部看到新添加的目录。

2,添加.pth文件

​ .pth类型的文件是Python专用的目录列表文件,把该类型的文件置于Python安装目录下Lib/site-packages文件夹中,Python编译起就会自动搜索,并添加其中的目录。

【示例】通过一个简单实例演示如何通过添加和使用.pth文件

1
2
3
4
5
6
7
8
9
第1步,新建文本文件,保存为test.pth,文件名可以任意,然后在其中输入下面目录。(E:/test)
第2步,把test.pth文件放置到Python安装目录下Lib/site-packages文件夹中。
第3步,在E:/test目录下新建hi.py文件,在其中输入代码:
def hello:
print('Hi,python')
第4步,新建Python文件,输入下面的代码,使用import语句导入hi模块
第5步,使用点语法,调用hi模块下的函数hello()
import hi:
hi.hello

【提示】

1
创建.pth文件后,应该重新打开测试文件,重新导入模块的Python文件,否则添加的目录可能会找不到。新建模块文件时,文件名不要与搜索路径下的文件出现重名,否则会被覆盖。

3,添加环境变量

【提示】

1
使用环境变量添加搜索路径,可以适用不同的版本Python,而.pth类型的文件仅被Python3.0新版本支持。

3,导入成员

使用import导入模块时,Python都会创建一个新的命名空间,并在该命名空间中执行.py文件的所有代码,同时访问模块中

的变量,函数或类名时,都需要添加模块名前缀。

​ 可以使用from…import语句将模块中具体的函数、类或变量等成员导入当前命名空间中直接使用,语法格式如下:

1
from 模块 import 成员

模块成员包括变量、函数或者类等,可以同时导入多个成员,多个成员之间使用逗号进行分隔,如果想要导入全部成员,可以使用通配符代替,例如:

1
from 模块 import *

【提示】

1
2
3
当导入模块中所有成员之后,可以使用print(dir())函数查看导入的所有成员:
from time import *
print(dir())
1
2
3
4
5
6
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'altzone', 'asctime', 'ctime', 'daylight', 'get_clock_info', 'gmtime', 'localtime', 'mktime', 'monotonic', 'monotonic_ns', 'perf_counter', 'perf_counter_ns', 'process_time', 'process_time_ns', 
'sleep', 'strftime', 'strptime', 'struct_time', 'thread_time', 'thread_time_ns', 'time', 'time_ns',
'timezone', 'tzname']

在以上输出列表中,除了系统默认的下面几个魔术成员外,其他都为time模块包含的成员。
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__',

【注意】

使用from…import 语句时,要确保当前命名的空间内不存在与导入名称一致的内容,否则将会引发冲突。最后导入的同名变量、函数或者类名将会覆盖前面的内容。因此,如果无法确定这种风险,则建议使用import语句直接导入模块,而不是导入模块成员。

4,使用标准模块

Python内置了很多标准模块,涵盖了核心功能、线程和进程、数据表示、文件格式、邮件和新闻消息处理、网络协议、国际化、多媒体相关模块、数据存储、工具和实用程序、其他模块等。其中核心功能又包括运行时服务、文字模式匹配、操作系统接口、数学运算、对象永久保存、网络和GUI等方面。其中常用模块说明如下所示:

image-20231103171927363

【示例】Python标准模块众多,下面结合JSON模块简单演示,了解如何使用它们

第1步,使用import语句JSON模块,先使用dir()函数查看该模块包含的所有函数和属性。

1
2
import json
print(dir(json))

输出为:

1
['JSONDecodeError', 'JSONDecoder', 'JSONEncoder', '__all__', '__author__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', '__version__', '_default_decoder', '_default_encoder', 'codecs', 'decoder', 'detect_encoding', 'dump', 'dumps', 'encoder', 'load', 'loads', 'scanner']

第2步,使用load()函数解码JSON数据,该函数返回Python字段的数据类型。可以使用下面命令查看该函数的基本用法:

1
print(help(json.loads))

第3步,把JSON字符串转换为Python字典对象

1
2
3
4
import json
str = '{"a":1,"b":2,"c":3,"d":4,"e":5}';
text = json.loads(str)
print(text)

输出为:

1
{'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}

5,使用第三方模块

​ 除了使用Python内置的标准模块外,也可以使用第三方模块。访问http://pypi.python.org/pypi,可以查看Python开源模块库。收录了许多来自全世界Python开发者贡献的模块,机会涵盖了想用Python做的任何事情。

【提示】

1
也可以访问https://www.ifd.uci.edu/~gohlke/pythonlibs/,下载Python扩展包的windows二进制文件。

使用第三方模块时,首先需要下载并安装该模块,然后就可以像使用标准模块一样导入并使用。下面介绍下载和安装模块,具体方法有两种:

1,下载模块并安装

在PyPI首页搜索模块,找到需要的模块后,单击Download files进入下载页面,然后可以选择下载二进制安装文件(.whl),或者源代码压缩包(.gz).

1
2
3
4
5
6
#对于二进制文件来说,可以参观下面的安装方法,使用pip命令进行安装,安装时把模块名替换成为二进制安装文件即可。注意,在命令行下要改变当前目录到安装目录下。
#对于源代码压缩包,先解压,并进入目录,然后执行下面的命令完成安装。
#编译源码
python setup.py bulid
#安装源码
python setup.py install

2,使用pip命令安装

直接通过Python提供的pip命令安装。pip命令安装格式如下:

1
pip install 模块名

pip命令会自动下载模块包并完成安装。pip命令会默认连接安装在国外的Python官方服务器进行下载。

【提示】

1
2
3
4
使用下面的命令可以卸载指定模块。
pip uninstall 模块名
使用下面可以查看已经安装的第三方模块。
pip list

6,模块兼容性

在导入模块时,可以使用别名来兼容不同的版本或模块差异,这样在运行时可以根据当前环境选择最合适的模块。

【示例】在python2.6之前,simplejson是独立的第三方库,从python2.6开始被内置,如果需要兼容其他版本,可以使用下面的写法进行兼容。

1
2
3
4
try:
import json
except ImportError:
import simplejson as json

这样就可以优先使用json,如果用户使用的是老版本python,就可以降级使用simplejson。当导入simplejson时,使用as指定别名为json,确保后续代码引用json都可以正常工作。由于Python是动态语言,只要在脚本中保持相同的函数接口和用法,无论导入哪个模块,后续代码都能正常工作,不需要大范围修改代码。

7,自定义模块

自定义模块的一般步骤如下。

第1步,新建Python文件,文件命名格式如下:

1
模块名 + .py

文件名及模块名,因此文件名不能够与Python内置模块重名。该文件名必须符合标识符规范。

第2步,在该文件中编写Python的源码,可以是变量、函数、类等功能代码。

第3步,把Python文件至于搜索路径中,如当前目录下等。

第4步,在脚本中使用import语句导入模块,然后就可以使用模块代码了。

【示例】演示一个简单的自定义模块设计过程

新建test1.py模块文件,然后输入下面的代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/user/bin/env python3
#_*_ coding:utf-8 _*_

'test1 模块'

__auther__ = '张三'

import sys

def saying():
args = sys.argv
if len(args)==1:
print('Hello,world!')
elif len(args)==2:
print('Hello,%s!' % args[1])
else:
print('参数太多!')

if __name__=='__main__':
saying()

在Python交互环境中导入test1模块,然后再调用模板中的函数saying()

1
2
import test1.py
test1.saying()

在交互环境中导入test1模板之后,没有直接打印”Hello,world!”,因为name==”main“为False,无法执行条件语句中的saying()代码。只有调用test1.saying()函数时,才会打印”hello,world”。

3,使用包

包是一个有层次的文件目录结构,它定义了有多个模块或多个子包组成的Python应用程序执行环境。使用包可以组织和规范代码,避免模块重名问题。

1,认识包

当使用的模块文件越来越多时,就需要对模块文件进行规划。

同时为了避免模块命名冲突,Python引入了按目录来组织模块的方法,称为包(Package)。一个文件夹就是一个包,包可以相互嵌套,就像文件目录一样,包的名字就是文件家的名字,包名通常全部小写,避免使用下划线。

在包目录中,init.py用于标识当前文件夹是一个包,在Python2中,包就是文件夹,但该文件夹下必须包含init.py,该文件的内容可以为空,init.py用于标识当前文件夹时一个包。在Python3中,即使目录下没有包含init.py文件,也能创建包,不过还是建议创建包时加上init.py

2,创建包

创建包实际上就是创建文件夹,同时在该文件夹中建立一个名为init.py的python文件。init.py文件可以为空,也可以编写任意python代码,在导入包时将自动执行init.py文件包含的代码。

【示例】在当前工作目录中,新建ecommerce(电子商务)文件夹,设计为一个应用项目,同时新建main.py文件,作为项目的启动程序。在ecommerce包里再添加一个payment文件夹,新建嵌套的字包,用来管理不同的付款方式,文件夹的层次结构如下所示:

1
2
3
4
5
6
7
8
9
10
parent_directory/
main.py
ecommerce/
__init__.py
database.py
products.py
payments/
__init__.py
paypal.py
authorizenet.py

其中,products.py文件定义了Product类。

1
2
class Product:
pass

其中,database.py文件定义了database类。

1
2
class database:
pass

3,导入包

创建包之后,就可以在包中创建模块,然后再使用import语句从包中加载模块。模块的导入方法有两种:绝对路径导入和相对路径导入。

1,绝对路径导入

通过指定包、模块、成员的完整路径进行导入。

【示例1】以上一节的实例为例,在main.py中访问products模块中的Product类,可以使用如下方法之一进行导入。

1
2
3
4
5
6
7
8
9
#方法一
import ecommerce.products
product = ecommerce.products.Product
#方法二
from ecommerce.products import Product
product = Product()
#方法三
from ecommerce import products
product = products.Product()

import 语句使用点号作为分隔符分割包、模块、成员。

【注意】

1
import语句只能导入模块或成员,不要使用import语句导入包,因为在脚本中不可以通过包访问模块,包对象只包括特殊的内置成员,如__doc__、__file__、__loader__、__name__、__package__、__package__、__path__、__spec__。

【提示】

1
如果模块中包含很多成员,建议使用第1种或第3种方式导入模块;如果模块中仅包含很少的成员,或者仅需要模块中个别成员,则可以考虑使用第2种方法导入具体的成员。

2,相对路径导入

在包(Package)中如果知道父模块的名称,那么就可以使用相对路径导入。具体方法有两种:

1
2
# . 在导入路径前面添加1个点号,表示当前目录。
# .. 在导入路径前面添加2个点号,标识父级目录

【示例2】以上一节的示例项目为例,当前在products模块中工作,想从相邻的database模块导入Database类,就可以使用下面相对路径导入。

1
from .database import Database

如果当前在commerce.payments.paypal模块中工作,需要引用父包中的database模块,就可以使用下面的相对路径导入:

1
from ..databse import Database

如果在commerce中新定义一个contact包,该包中新建email模块,需要将email模块的sendEmail函数导入到paypal模块中,则导入方法如下:

1
from ..contact.email import sendEmail

【注意】

1
使用相对路径导入模块或成员时,都必须从项目入口程序开始执行,不能够把模块作为脚本直接执行,否则Python解释器将以当前模块作为入口程序,当前目录作为工作目录,就无法理解整个项目的目录层次关系。因此,如果不以一个完整的项目进行运行,就不要使用相对路径导入内容。

4,案例实战

本节将结合实例介绍常用的内置模块的简单应用。

1,使用日期和时间模块

在开发中经常需要处理日期和时间,转换日期格式等操作。Python提供了time,datatime和calender这三个与时间相关的模块。熟悉这些标准模块的基本功能和使用,就能满足日常的开发需求。

1,time模块

在time模块中,通常有3种时间表达式

时间戳

时间戳表示从1970年1月1日00:00:00点开始按秒计算时间的偏移量,以浮点型表示。可以使用time模块的time()或者clock()等函数获取。例如:

1
2
3
import time
now = time.time()
print(now)
1
1699063787.2477338

【提示】

时间戳适合做日期运算,但是对于1970年之前或者太久之前的时间就无法表示了,UNIX和windows只支持到2038年。

格式化的自符串

可以根据需要选取各种日期、时间显示格式,其中最简单的方法是使用localtime()和asctime()函数。

例如:

1
2
3
import time 
now = time.asctime(time.localtime())
print(now)

在上面的代码中,首先使用localtime()函数获取本地当前时间,返回为元组对象,然后通过asctime()函数进行格式化显示。

1
Sat Nov  4 10:10:16 2023

也可以使用time模块中的strftime()函数来格式化日期:

1
2
3
import time
print(time.strftime("%Y-%m-%d %H:%M:%S",time.localtime()))
print(time.strftime("%a %b %c %H:%M:%S %Y",time.localtime()))

输出为:

1
2
2023-11-04 10:10:35
Sat Nov Sat Nov 4 10:10:35 2023 10:10:35 2023

时间元组

很多函数使用一个元组包含9个数字来处理时间,者9个元素分别为年(tm_year),月(tm_mon),日(tm_mday),时(tm_hour),分(tm_min),秒(tm_sec),一周中的第几天(tm_wday),一年中的第几天(tm_yday),是否为夏时令(tm_isdst)。具体说明如下:

例如,下面使用localtime()函数获取当前时间的元组

1
2
3
import time
now = time.localtime()
print(now)

输出为:

1
time.struct_time(tm_year=2023, tm_mon=11, tm_mday=4, tm_hour=10, tm_min=11, tm_sec=6, tm_wday=5, tm_yday=308, tm_isdst=0)

2,datetime模块

datetime模块重新封装了time模块,提供更多接口,包含6个类,简单说明如下:

1
2
3
4
5
6
#date:日期对象,常用属性有year、month、day
#time:事件对象
#datetime:日期事件对象,常用属性hour、minute、second、microsecond。
#timedelta:时间间隔,勇于时间的加减,即两个时间点之间的长度
#tznfo:时区对象,由于是抽象类,不能直接实现。
#timezone:tzinfo的子类,用于表示相对于时间标准(UTC)的偏移量

【示例1】使用datetime模块中date类的now()函数获取当前时间,然后分别使用date(),time(),today()函数分别获取日期、时间和日期格式信息。

1
2
3
4
5
6
7
import datetime
now = datetime.datetime.now()
print(now)
print(now.date())
print(now.time())
today = datetime.date.today()
print(now.today())

输出结果:

1
2
3
4
2023-11-04 10:38:03.365221
2023-11-04
10:38:03.365221
2023-11-04

【示例2】获取时间差。本例使用now()函数获取当前时间,然后计算一个for循环执行10万次所花费的时间,单位为毫秒。

1
2
3
4
5
6
7
8
import datetime
start = datetime.datetime.now()
sum = 0
for i in range(100000):
sum += 1
end = datetime.datetime.now()
len = (end-start).microseconds
print(len)

运行结果:

1
18986

差值不只是可以查看相差多少秒,还可以查看天(days)、秒(seconds)和微秒(microseconds)。

【示例3】计算当前时间向后8个小时的时间。

1
2
3
4
import datetime
start = datetime.datetime.now()
end= start + datetime.timedelta(hour=8)
print(end)

运算结果:

1
2023-11-04 18:59:38.746353

timedelta类用来计算两个datetime对象的差值,构造函数的语法格式如下:

1
datetime.timedelta(day=0,hours=0,days=0,weeks=0)

其中参数都可选,默认值为0.使用这种方法可以计算:天(days)、小时(hours)、分钟(minutes)、秒(seconds)、微秒(microseconds)。

3,calender模块

calender模块用来处理年历和月历。例如:

1
2
3
import calendar
cal = calendar.month(2020,7)
print(cal)

输出为:

1
2
3
4
5
6
7
     July 2020
Mo Tu We Th Fr Sa Su
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31

2,使用随机数模块

random模块主要用于生成随机数。该模块提供的常用函数说明如下:

1
2
3
4
5
6
7
#random.random():用于生成一个0~1.0范围内的随机浮点数(0<=n<1.0)
#random.uniform(a,b):用于生成一个指定范围内的随机浮点数(a<=n<b)
#random.randint(a,b):用于生成一个指定范围内的随机整数(a<=n<=b)
#random.randrange([start=0],stop[,step=1]):从指定范围内,按指定步长递增的集合中获取一个随机数。其中参数start表示范围内起点,包含在范围内;参数stop表示范围内终点,不包含在范围内;参数step表示增长的步长。
#random.choice(sequence):从序列sequence对象中获取一个随机数。注意,choice()函数抽取的元素可能会出现重复
#random.shuffle(x[,random]):用于将一个列表中的元素打乱。
#random.sample(sequence,k):从指定序列sequence中随机获取指定长度的片段,参数k表示关键字参数,必须设置,获取元素的个数。注意,sample()函数抽取的元素是不重复的,同时不会修改原有序列。

【示例1】使用random模块随机生成各种类型的数据。

1
2
3
4
5
6
7
import random
print(random.random())
print(random.randint(1,3))
print(random.randrange(1,3))
print(random.choice([1,2,[3,5]]))
print(random.sample([1,'23',[4,5]],3))
print(random.uniform(1,3))

运算结果:

1
2
3
4
5
6
0.16024680687171267
2
2
[3, 5]
[1, '23', [4, 5]]
1.2353607939701379

【示例2】使用random模块生成一个4位验证码。

1
2
3
4
5
6
7
8
9
import random
code_list = []
for i in range(4):
num1 = random.randint(1,9)
strq1 = chr(random.randint(65,90))
s = random.choice([num1,strq1])
code_list.append(str(s))
code = ''.join(code_list)
print(code)

运行结果:

1
A24S

3,使用加密模块

Python的hashlib模块用来进行hash或者md5加密,这种加密是不可逆的,也称为摘要算法。该模块支持Openssl库提供的所有算法,包括MD5,sha1、sha224、sha256、sha512等。

该模块常用属性和方法说明如下:

1
2
3
4
5
6
7
#algorithms_available:列出所有可用的加密算法,如(MD5,sha1、sha224、sha256、sha384、sha512)
#digest_size:加密后的哈希对象的字节大小
#md5()或sha1()等:创建一个md5或者sha1等加密模式的哈希对象。
#update(arg):用字符串参数来更新哈希对象,如果同一个哈希对象重复调用该方法,如m.update(a);m.update(b),则等于 m.update(a+b)
#digest():以二进制数据字符串返回摘要信息。
#hexdigest():以十六进制数据字符串返回摘要信息。
#copy():复制哈希对象。

【示例】本示例是一个简单的加密示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import hashlib
string = "Python"
md5 = hashlib.md5()
md5.update(string.encode('utf-8'))
res = md5.hexdigest()
print("md5加密结果",res)

sha1 = hashlib.sha1()
sha1.update(string.encode('utf-8'))
res1 = sha1.hexdigest()
print("sha1加密结果",res1)

sha256 = hashlib.sha256()
sha256.update(string.encode('utf-8'))
res2 = sha256.hexdigest()
print("sha256加密结果",res2)

sha384 = hashlib.sha384()
sha384.update(string.encode('utf-8'))
res3 = sha384.hexdigest()
print("sha384加密结果",res3)

sha512 = hashlib.sha512()
sha512.update(string.encode('utf-8'))
res4 = sha512.hexdigest()
print("sha512加密结果",res4)

运算结果

1
2
3
4
5
md5加密结果 a7f5f35426b927411fc9231b56382173
sha1加密结果 6e3604888c4b4ec08e2837913d012fe2834ffa83
sha256加密结果 18885f27b5af9012df19e496460f9294d5ab76128824c6f993787004f6d9a7db
sha384加密结果 3775eb53318c3a4717264af862e03a7807511c350b4342c062362cab558ef0169753f026bcb4ced8561b42fbccf3ea71
sha512加密结果 fd9d4d5b7a8a8fae6b1bc099b799110f7e4338606e2610f5d9506a4346e0c3bfbc525f4eed1e05aa8c6f46b8efff526ec48b500928a1b341ade5a7855f533932

4,使用JSON模块

JSON(JavaScipt Object Notation)是一种轻量级的数据交换格式,JSON模块提供了4个方法用来实现Python对象与JSON数据进行快速交换,简单说明如下:

1
2
3
4
#dumps():将Python对象序列化为JSON字符串表示。
#dump():将Python对象序列化为JSON字符串,然后保存到文件中
#loads():把JSON字符串反序列化为Python对象
#load():读取文件内容,然后反序列化为Python对象

【示例1】将字典对象序列化为JSON字符串,然后再反序列化为Python的字典类型的对象

1
2
3
4
5
6
import json
a = {"name":"Tom","age":23}
b = json.dumps(a)
print(b)
c = json.loads(b)
print(c["age"])

运行结果:

1
2
{"name": "Tom", "age": 23}
23

【示例2】下面示例设计将字典对象序列化为字符串,然后使用dump()方法保存到test.json文件中,再使用load()方法从test.json文件中读取字符串,并转换为字典对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
import json
a = {"name":"Tom","age":23}
with open("test.json","w",encoding='utf-8') as f:
#indent表示格式化保存字符串,默认为None,小于0为零个空格
json.dump(a,f,indent=4)
#f.write(json.dumps(a,indent=4)) 与json.dump()效果一致
with open("test.json","r",encoding='utf-8') as f:
b = json.load(f)
f.seek(0) #重新把文件指针移到文件开头
c = json.loads(f.read()) #与json.load(f)执行效果一样
print(b)
print(c)

运行结果:

1
2
{'name': 'Tom', 'age': 23}
{'name': 'Tom', 'age': 23}

Python对象与JSON对象相互转换表

1
2
3
Python对象:JSON对象 
dict:object list,tuple:array str:string int,float:number
True:true False:false None:null

5,使用图像模块

PIL(Python Imaging Library)是Python图像处理标准库,功能强大,简单易用。PIL仅支持到Python2.7,升级后的版本改为Pillow,支持Python3版本,并增加了很多新特性。

1,安装Pillow

在命令行下通过pip命令安装。

1
pip install pillow

2,操作图像

在PIL中,图像的常用属性和方法简单概述如下。

图像的基本操作

1
2
3
4
5
Image.open(file[,mode]):打开图像,生成Image对象。file表示要打开的图像文件,mode表示图像模式。
Image.new(mode,size[,color]):创建图像,生成Image对象
image.show():显示图像
image.save(file[,format]):保存图像。参数format表示文件格式,如果省略,将根据file的扩展名确定。
image.copy():复制图像

图像的基本属性

1
2
3
image.format:图像来源,如果图像不是从文件读取,则值为None
image.size:图像大小
image.mode:图像模式

图像变换操作

1
2
3
4
5
image.resize((width,height)):改变图像大小
image.rotate(angle):旋转图像。angle表示角度,逆时针旋转
image.transpose(method):反转图像。参数method为常量,表示翻转方式。
image.convert(mode):转换图像模式
image.filter(filter):对图像进行特效处理

图像合成、裁切和分离

1
2
3
4
5
image.blend(img1,img2,alpha):合成两张图片,alpha表示img1和img2的比例
image.crop(box):根据box参数裁切图片,生成裁切的Image对象。
image.paste(img,box):粘贴box大小的区域到原图像中
r,g,b=image.split():根据通道分离图像,r,g,b表示返回的单色图像对象
image.merge("RGB",(r,g,b)):根据颜色通道,将r,g,b合成单一图像。

图像的像素点操作:

1
2
3
image.point(function):对图片中的每一个点执行function函数。
image.getpixel((x,y)):获取指定像素点的颜色值。
image.putpixel((x,y)):设置指定像素点的颜色值。

【示例1】先打开一个图像文件,然后获取其尺寸,再缩小图像大小,最后命名为thumbnail.jpg保存到当前目录下。

1
2
3
4
5
6
7
from Pillow import image
im = Image.open('Python.jpg')
w,h = im.size
print('Origenal image size: %x%s' % (w,h))
im.thumbnail((w//2,h//2))
print('Resize image to: %sx%s' % (w//2,h//2))
im.save('thumbnail.jpg','jpeg')

【示例2】打开一个图像,然后旋转90°,之后再显示出来

1
2
3
4
from PIL import Image
im = Image.open('python.jpg')
dst_image = im.rotate(90)
dst_image.show()

【注意】

image-20231104201720764

image-20231104201641823

【示例3】在PIL的ImageDraw模块提供了一系列绘图方法,可以直接绘图。本示例利用该模块的方法生成字母验证码图片,将其命名为code.jpg,然后保存到当前目录。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#第1步,从PIL模块中导入图像类、绘图类、图像字体类和图像特效类。
from PIL import Image,ImageDraw,ImageFont,ImageFilter
#第2步,初始化设置
import random
def rndChar():
return chr(random.randint(65,90))
def rndColor():
return (random.randint(64,255),random.randint(64,255),random.randint(64,255))
def rndColor():
return (random.randint(32,127),random.randint(32,127),random.randint(32,127))
width = 60 * 4
height = 60
3步,创建图像对象、字体对象、会话对象
#创建对象
image = Image.new('RGB',(width,height),(255,255,255))
font = ImageFont.truetype('arialuni,ttf',36)
draw = ImageDraw.Draw(image)
#生成麻点背景
for i in range(width):
for y in range(height):
draw.point((x,y),fill=rndColor())
#在画布上生成随机字符
for t in range(4):
draw.text((60 * t + 10,10),rndChar(),font=font,fill=rndColor2())
image = image.filler(ImageFilter.BLUE)
#第4步,保存图片
image.save('code.jpg','jpeg')