目录

1. 前言

2. Pillow

3. requests

4. chardet

5. psutil


1. 前言

除了内建的模块外,Python还有大量的第三方模块。

基本上,所有的第三方模块都会在PyPI - the Python Package Index上注册,只要找到对应的模块名字,即可用pip安装。

此外,在安装第三方模块一节中,我们强烈推荐安装Anaconda,安装后,数十个常用的第三方模块就已经就绪,不用pip手动安装。

本篇博客介绍常用的第三方模块。

 

2. Pillow

PIL:Python Imaging Library,已经是Python平台事实上的图像处理标准库了。PIL功能非常强大,但API却非常简单易用。

由于PIL仅支持到Python 2.7,加上年久失修,于是一群志愿者在PIL的基础上创建了兼容的版本,名字叫Pillow,支持最新Python 3.x,又加入了许多新特性,因此,我们可以直接安装使用Pillow。

  • 安装Pillow

如果安装了Anaconda,Pillow就已经可用了。否则,需要在命令行下通过pip安装:

pip install pillow

如果遇到Permission denied安装失败,请加上sudo重试。

  • 操作图像

来看看最常见的图像缩放操作,只需三四行代码:

from PIL import Image

im = Image.open('/Users/apple/Desktop/timg.jpg')
w,h = im.size

print('Original image size: %sx%s' % (w, h))
# 缩放到50%:
im.thumbnail((w//2,h//2))
print('Resize image to: %sx%s' % (w//2, h//2))
# 把缩放后的图像用jpeg格式保存:
im.save('thumbnail.jpg','jpeg')

python中的dis python中的第三方模块_Python

其他功能如切片、旋转、滤镜、输出文字、调色板等一应俱全。

比如,模糊效果也只需几行代码:

from PIL import Image, ImageFilter

# 打开一个jpg图像文件
im = Image.open('/Users/apple/Desktop/timg.jpg')
# 应用模糊滤镜:
im2 = im.filter(ImageFilter.BLUR)
im2.save('blur.jpg', 'jpeg')

PIL的ImageDraw提供了一系列绘图方法,让我们可以直接绘图。比如要生成字母验证码图片:

from PIL import Image, ImageDraw, ImageFont, ImageFilter

import random

# 随机字母:
def rndChar():
    return chr(random.randint(65, 90))

# 随机颜色1:
def rndColor():
    return (random.randint(64, 255), random.randint(64, 255), random.randint(64, 255))

# 随机颜色2:
def rndColor2():
    return (random.randint(32, 127), random.randint(32, 127), random.randint(32, 127))

# 240 x 60:
width = 60 * 4
height = 60
image = Image.new('RGB', (width, height), (255, 255, 255))
# 创建Font对象:
font = ImageFont.truetype('Arial.ttf', 36) #设置字体类型和位置
# 创建Draw对象:
draw = ImageDraw.Draw(image)
# 填充每个像素:
for x 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.filter(ImageFilter.BLUR)
image.save('code.jpg', 'jpeg')

我们用随机颜色填充背景,再画上文字,最后对图像进行模糊,得到验证码图片如下:

python中的dis python中的第三方模块_Python_02

如果运行的时候报错:

IOError: cannot open resource

这是因为PIL无法定位到字体文件的位置,可以根据操作系统提供绝对路径,比如:

'/Library/Fonts/Arial.ttf'

要详细了解PIL的强大功能,请请参考Pillow官方文档:

https://pillow.readthedocs.org/

  • 小结

PIL提供了操作图像的强大功能,可以通过简单的代码完成复杂的图像处理。

 

3. requests

我们已经讲解了Python内置的urllib模块,用于访问网络资源。但是,它用起来比较麻烦,而且,缺少很多实用的高级功能。

更好的方案是使用requests。它是一个Python第三方库,处理URL资源特别方便。

  • 安装requests

如果安装了Anaconda,requests就已经可用了。否则,需要在命令行下通过pip安装:

pip install requests
  • 使用requests

要通过GET访问一个页面,只需要几行代码:

import requests

response = requests.get('https://www.douban.com')
print(response.statu s_code)
print(response.text)

python中的dis python中的第三方模块_常用第三方模块_03

对于带参数的URL,传入一个dict作为params参数:

response = requests.get('https://www.douban.com/search',params={'q':'python','cat':'1001'})
response.url

python中的dis python中的第三方模块_Image_04

requests自动检测编码,可以使用encoding属性查看:

response.encoding

python中的dis python中的第三方模块_Python_05

无论响应是文本还是二进制内容,我们都可以用content属性获得bytes对象:

response.content

python中的dis python中的第三方模块_Image_06

requests的方便之处还在于,对于特定类型的响应,例如JSON,可以直接获取:

r = requests.get('https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20%3D%202151330&format=json')
r.json()

需要传入HTTP Header时,我们传入一个dict作为headers参数:

import requests
headers = {'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'}
response = requests.get('https://www.douban.com',headers=headers)
response.text

要发送POST请求,只需要把get()方法变成post(),然后传入data参数作为POST请求的数据:

r = requests.post('https://accounts.douban.com/login', data={'form_email': 'abc@example.com', 'form_password': '123456'})

requests默认使用application/x-www-form-urlencoded对POST数据编码。如果要传递JSON数据,可以直接传入json参数:

params = {'key': 'value'}
r = requests.post(url, json=params) # 内部自动序列化为JSON

类似的,上传文件需要更复杂的编码格式,但是requests把它简化成files参数:

upload_files = {'file': open('report.xls', 'rb')}
r = requests.post(url,files=upload_files)

在读取文件时,注意务必使用'rb'即二进制模式读取,这样获取的bytes长度才是文件的长度。

把post()方法替换为put(),delete()等,就可以以PUT或DELETE方式请求资源。

除了能轻松获取响应内容外,requests对获取HTTP响应的其他信息也非常简单。例如,获取响应头:

response = requests.get('https://www.baidu.com')
print(response.headers)
print(response.headers['Content-Type'])

python中的dis python中的第三方模块_python中的dis_07

requests对Cookie做了特殊处理,使得我们不必解析Cookie就可以轻松获取指定的Cookie:

print(response.cookies)

要在请求中传入Cookie,只需准备一个dict传入cookies参数:

cs = {'token': '12345', 'status': 'working'}
response = requests.get(url,cookies=cs)

最后,要指定超时,传入以秒为单位的timeout参数:

response = requests.get(url,timeout=2.5) #2.5s后未响应 则超时
  • 小结

用requests获取URL资源,就是这么简单!

 

4. chardet

字符串编码一直是令人非常头疼的问题,尤其是我们在处理一些不规范的第三方网页的时候。虽然Python提供了Unicode表示的str和bytes两种数据类型,并且可以通过encode()和decode()方法转换,但是,在不知道编码的情况下,对bytes做decode()不好做。

对于未知编码的bytes,要把它转换成str,需要先“猜测”编码。猜测的方式是先收集各种编码的特征字符,根据特征字符判断,就能有很大概率“猜对”。

当然,我们肯定不能从头自己写这个检测编码的功能,这样做费时费力。chardet这个第三方库正好就派上了用场。用它来检测编码,简单易用。

  • 安装chardet

如果安装了Anaconda,chardet就已经可用了。否则,需要在命令行下通过pip安装:

pip install chardet
  • 使用chardet

当我们拿到一个bytes时,就可以对其检测编码。用chardet检测编码,只需要一行代码:

import chardet
chardet.detect(b'Hello World!')

python中的dis python中的第三方模块_Python_08

检测出的编码是ascii,注意到还有个confidence字段,表示检测的概率是1.0(即100%)。

我们来试试检测GBK编码的中文:

data = '离离原上草,一岁一枯荣'.encode('gbk')
chardet.detect(data)

python中的dis python中的第三方模块_Python_09

检测的编码是GB2312,注意到GBK是GB2312的超集,两者是同一种编码,检测正确的概率是74%,language字段指出的语言是'Chinese'。

对UTF-8编码进行检测:

data = '离离原上草,一岁一枯荣'.encode('utf-8')
chardet.detect(data)

python中的dis python中的第三方模块_Python_10

我们再试试对日文进行检测:

data = '最新の主要ニュース'.encode('euc-jp')
chardet.detect(data)

python中的dis python中的第三方模块_常用第三方模块_11

可见,用chardet检测编码,使用简单。获取到编码后,再转换为str,就可以方便后续处理。

chardet支持检测的编码列表请参考官方文档Supported encodings。

  • 小结

使用chardet检测编码非常容易,chardet支持检测中文、日文、韩文等多种语言。

 

5. psutil

用Python来编写脚本简化日常的运维工作是Python的一个重要用途。在Linux下,有许多系统命令可以让我们时刻监控系统运行的状态,如ps,top,free等等。要获取这些系统信息,Python可以通过subprocess模块调用并获取结果。但这样做显得很麻烦,尤其是要写很多解析代码。

在Python中获取系统信息的另一个好办法是使用psutil这个第三方模块。顾名思义,psutil = process and system utilities,它不仅可以通过一两行代码实现系统监控,还可以跨平台使用,支持Linux/UNIX/OSX/Windows等,是系统管理员和运维小伙伴不可或缺的必备模块。

  • 安装psutil

如果安装了Anaconda,psutil就已经可用了。否则,需要在命令行下通过pip安装:

pip install psutil
  • 获取CPU信息
import psutil

print(psutil.cpu_count()) #cpu逻辑数量
print(psutil.cpu_count(logical=False)) #cpu物理核心
# 4说明是4核超线程, 8则是8核非超线程

python中的dis python中的第三方模块_Python基础Pro_12

统计CPU的用户/系统/空闲时间:

psutil.cpu_times()

python中的dis python中的第三方模块_Python_13

再实现类似top命令的CPU使用率,每秒刷新一次,累计10次:

for x in range(10):
    print(psutil.cpu_percent(interval=1,percpu=True))

python中的dis python中的第三方模块_Python_14

  • 获取内存信息

使用psutil获取物理内存和交换内存信息,分别使用:

print(psutil.virtual_memory())
print(psutil.swap_memory())

python中的dis python中的第三方模块_Python_15

返回的是字节为单位的整数,可以看到,总内存大小是17179869184 = 16 GB,已用7501750272 = 6.7 GB,使用了50.3%。

而交换区大小是2147483648 = 2 GB。

  • 获取磁盘信息

可以通过psutil获取磁盘分区、磁盘使用率和磁盘IO信息:

print(psutil.disk_partitions()) #磁盘分区信息
print(psutil.disk_usage('/')) #磁盘使用信息
print(psutil.disk_io_counters())#磁盘IO

python中的dis python中的第三方模块_Python基础Pro_16

可以看到,磁盘'/'的总容量是250790436864 = 256 GB,使用了31.5%。文件格式是apfs,opts中包含rw表示可读写,journaled表示支持日志。

  • 获取网络信息

psutil可以获取网络接口和网络连接信息:

print(psutil.net_io_counters()) # 获取网络读写字节/包的个数
print(psutil.net_if_addrs()) #获取网络接口信息
print(psutil.net_if_stats()) # 获取网络接口状态

python中的dis python中的第三方模块_常用第三方模块_17

要获取当前网络连接信息,使用net_connections():

psutil.net_connections()

你可能会得到一个AccessDenied错误,原因是psutil获取信息也是要走系统接口,而获取网络连接信息需要root权限,这种情况下,可以退出Python交互环境,用sudo重新启动:

python中的dis python中的第三方模块_常用第三方模块_18

  • 获取进程信息

通过psutil可以获取到所有进程的详细信息:

print(psutil.pids()) # 所有进程ID
p = psutil.Process(3776) # 获取指定进程ID=3776,其实就是当前Python交互环境
print(p.name())# 进程名称
print(p.exe()) #进程exe路径
print(p.cwd()) #进程工作目录
print(p.cmdline()) # 进程启动的命令行
print(p.ppid()) # 父进程ID
print(p.parent()) # 父进程
print(p.children()) # 子进程列表
print(p.status())# 进程状态
print(p.username())# 进程用户名
print(p.create_time()) # 进程创建时间
print(p.terminal())# 进程终端
print(p.cpu_times()) # 进程使用的CPU时间
print(p.memory_info()) # 进程使用的内存
print(p.open_files()) # 进程打开的文件
print(p.connections()) # 进程相关网络连接
print(p.num_threads()) # 进程的线程数量
print(p.threads())# 所有线程信息
print(p.environ()) # 进程环境变量
print(p.terminate()) # 结束进程

和获取网络连接类似,获取一个root用户的进程需要root权限,启动Python交互环境或者.py文件时,需要sudo权限.

psutil还提供了一个test()函数,可以模拟出ps命令的效果:

python中的dis python中的第三方模块_Image_19

  • 小结

psutil使得Python程序获取系统信息变得易如反掌。

psutil还可以获取用户信息、Windows服务等很多有用的系统信息,具体请参考psutil的官网:https://github.com/giampaolo/psutil