Skip to content

Python 常用第三方模块:站在巨人的肩膀上

引言:从"自带电池"到"应用商店"

上一篇我们讲了 Python 的内建模块——就像手机出厂预装的计算器、日历,开箱即用。

但真正的威力在于第三方模块——全球的 Python 开发者编写了超过 40 万个第三方包,发布在 PyPI(Python Package Index)上。这就像手机的应用商店:想修图?有 Pillow;想发网络请求?有 requests;想识别文件编码?有 chardet;想监控系统资源?有 psutil。

安装第三方模块只需要一行命令:

bash
pip install 模块名

生活化理解:内建模块是毛坯房自带的硬装(水电、地板),第三方模块是你自己买的家电(冰箱、洗衣机、空调)——按需安装,即装即用。

这一篇,我们深入讲解 4 个最经典、使用最广泛的第三方模块:Pillow(图像处理)、requests(网络请求)、chardet(编码检测)、psutil(系统监控)。每个模块都会讲透核心功能、实战案例和常见误区。


准备工作:pip 使用须知

在开始之前,先确保你会正确安装第三方模块:

bash
# 安装单个模块
pip install Pillow
pip install requests
pip install chardet
pip install psutil

# 一次装多个
pip install Pillow requests chardet psutil

# 指定版本
pip install requests==2.31.0

# 升级
pip install --upgrade requests

# 卸载
pip uninstall requests

# 查看已安装的模块
pip list

# 查看某个模块的详细信息
pip show requests

重要提醒:请务必在虚拟环境(venv)中安装,别污染全局环境!

国内加速:如果下载慢,可以使用国内镜像源:

bash
pip install requests -i https://pypi.tuna.tsinghua.edu.cn/simple

一、Pillow:Python 的"图像处理车间"

1.1 模块简介

Pillow 是大名鼎鼎的 PIL(Python Imaging Library)的分支和继承者。PIL 早已停止更新(停留在 Python 2.x),Pillow 接手并持续维护至今,是 Python 图像处理的事实标准。

生活化理解:Pillow 就是一个数字暗房 + 修图工作室——裁剪、缩放、旋转、加水印、调滤镜、转格式,样样都行。

bash
pip install Pillow

注意:安装名是 Pillow(大写),导入名是 PIL(历史遗留):

python
from PIL import Image  # ✅ 正确
import Pillow           # ❌ 错误

1.2 打开、查看、保存图片

python
from PIL import Image

# 打开图片
im = Image.open('photo.jpg')

# 查看基本信息
print(im.format)  # 'JPEG' — 图片格式
print(im.size)    # (1920, 1080) — 宽×高(像素)
print(im.mode)    # 'RGB' — 色彩模式

# 保存为另一种格式(格式转换)
im.save('photo.png')  # 根据扩展名自动选择格式

常见色彩模式

模式含义每像素通道
RGB红绿蓝三原色3
RGBARGB + 透明度4
L灰度图(黑白)1
1二值图(纯黑白)1 位

1.3 缩放与裁剪

python
from PIL import Image

im = Image.open('photo.jpg')

# 缩放到指定尺寸
im_resized = im.resize((400, 300))
im_resized.save('photo_small.jpg')

# 等比缩放:制作缩略图(不会变形)
im.thumbnail((200, 200))  # 最长边不超过200
im.save('photo_thumb.jpg')

# 裁剪:crop((左, 上, 右, 下))
im_crop = im.crop((100, 100, 500, 400))
im_crop.save('photo_crop.jpg')

resize vs thumbnail 的区别

  • resize((400, 300)):强制缩放到 400×300,可能变形
  • thumbnail((200, 200)):等比缩放,最长边不超过 200,不会变形,且直接修改原对象。

1.4 旋转与翻转

python
# 旋转 45 度(逆时针)
im.rotate(45).save('rotated.jpg')

# 旋转并填充空白区域为白色
im.rotate(45, expand=True, fillcolor='white').save('rotated_full.jpg')

# 左右镜像翻转
im.transpose(Image.FLIP_LEFT_RIGHT).save('flip.jpg')

# 上下翻转
im.transpose(Image.FLIP_TOP_BOTTOM).save('flop.jpg')

rotateexpand 参数:图片旋转 45 度后,四个角会超出原来的矩形范围。expand=False(默认)会裁掉超出部分;expand=True 会扩大画布容纳完整图片。

1.5 滤镜与图像增强

python
from PIL import Image, ImageFilter, ImageEnhance

im = Image.open('photo.jpg')

# 模糊效果(常用于隐私打码)
im.filter(ImageFilter.GaussianBlur(radius=10)).save('blur.jpg')

# 轮廓效果
im.filter(ImageFilter.CONTOUR).save('contour.jpg')

# 锐化
im.filter(ImageFilter.SHARPEN).save('sharp.jpg')

# 调整亮度(1.0=原始,>1变亮,<1变暗)
bright = ImageEnhance.Brightness(im).enhance(1.5)
bright.save('brighter.jpg')

# 调整对比度
contrast = ImageEnhance.Contrast(im).enhance(1.3)
contrast.save('contrast.jpg')

# 调整色彩饱和度(0=黑白)
color = ImageEnhance.Color(im).enhance(0.0)
color.save('gray.jpg')

1.6 加水印

python
from PIL import Image, ImageDraw, ImageFont

im = Image.open('photo.jpg')

# 创建画笔
draw = ImageDraw.Draw(im)

# 加载字体(Windows 自带微软雅黑)
font = ImageFont.truetype('msyh.ttc', 36)

# 在右下角绘制文字水印
text = '@我的版权'
w, h = im.size
draw.text((w - 300, h - 60), text, font=font, fill=(255, 255, 255, 128))

im.save('watermarked.jpg')

1.7 图片拼接

python
from PIL import Image

im1 = Image.open('a.jpg')
im2 = Image.open('b.jpg')

# 创建一张新画布(宽度=两图之和)
new_im = Image.new('RGB', (im1.width + im2.width, im1.height))
new_im.paste(im1, (0, 0))           # 左图贴在 (0,0)
new_im.paste(im2, (im1.width, 0))   # 右图贴在左图右边
new_im.save('merged.jpg')

1.8 实战案例:批量生成缩略图

python
from PIL import Image
from pathlib import Path

def make_thumbnails(src_dir, dst_dir, size=(300, 300)):
    """批量把 src_dir 下的图片生成缩略图到 dst_dir"""
    Path(dst_dir).mkdir(exist_ok=True)

    for file in Path(src_dir).glob('*.jpg'):
        im = Image.open(file)
        im.thumbnail(size)
        out_path = Path(dst_dir) / file.name
        im.save(out_path)
        print(f'处理完成: {file.name}')

make_thumbnails('photos', 'thumbnails')

1.9 常见误区

误区 1Image.open() 后忘记关闭文件。

真相:大文件处理时最好用 with 或显式 close()

python
with Image.open('big.jpg') as im:
    im.thumbnail((300, 300))
    im.save('thumb.jpg')

误区 2:处理 JPG 时透明度丢了。

真相:JPG 不支持透明通道。如果图片是 RGBA 模式,保存为 JPG 前要先转换:

python
im = Image.open('icon.png')  # RGBA
im.convert('RGB').save('icon.jpg')  # 先转成 RGB

误区 3resizethumbnail 混用出错。

真相resize 返回新对象thumbnail 原地修改不返回值:

python
im2 = im.resize((400, 300))  # im 不变,im2 是新图
im.thumbnail((200, 200))     # im 被直接修改,返回 None
im3 = im.thumbnail((100, 100))  # ❌ im3 是 None!

二、requests:最好用的"网络快递员"

2.1 模块简介

Python 自带的 urllib 能发 HTTP 请求,但接口啰嗦。requests 的口号是 "HTTP for Humans"(为人类设计的 HTTP 库),接口优雅到令人惊叹,是 Python 生态中下载量最高的库之一。

bash
pip install requests

urllib vs requests 对比

python
# urllib 发 POST 请求
from urllib.request import urlopen, Request
from urllib.parse import urlencode
data = urlencode({'key': 'value'}).encode('utf-8')
req = Request('https://httpbin.org/post', data=data, method='POST')
with urlopen(req) as resp:
    result = resp.read().decode('utf-8')

# requests 发同样的请求
import requests
r = requests.post('https://httpbin.org/post', data={'key': 'value'})
result = r.text

2.2 GET 请求

python
import requests

# 最简单的 GET
r = requests.get('https://httpbin.org/get')

# 查看响应
print(r.status_code)  # 200 — HTTP 状态码
print(r.text)         # 响应内容(字符串)
print(r.headers)      # 响应头(类字典对象)
print(r.encoding)     # 'utf-8' — 编码

# 带查询参数(自动拼接到 URL)
r = requests.get('https://httpbin.org/get', params={'name': '张三', 'page': 2})
print(r.url)  # https://httpbin.org/get?name=%E5%BC%A0%E4%B8%89&page=2

# 带请求头
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'}
r = requests.get('https://httpbin.org/get', headers=headers)

# 设置超时(重要!防止程序卡死)
r = requests.get('https://httpbin.org/get', timeout=5)  # 5秒超时

2.3 POST 请求

python
import requests

# 表单提交(application/x-www-form-urlencoded)
r = requests.post('https://httpbin.org/post', data={'username': 'admin'})

# JSON 提交(application/json)— 现代 API 的主流
r = requests.post('https://httpbin.org/post', json={'username': 'admin', 'age': 18})

# 上传文件(multipart/form-data)
files = {'file': open('report.xlsx', 'rb')}
r = requests.post('https://httpbin.org/post', files=files)

data= vs json= 的区别

参数Content-Type适用场景
data={'k': 'v'}application/x-www-form-urlencoded传统网页表单
json={'k': 'v'}application/json现代 RESTful API

2.4 处理 JSON 响应

现代 API 几乎都返回 JSON,requests 内置了解析方法:

python
import requests

r = requests.get('https://httpbin.org/json')
data = r.json()  # 自动解析为 Python 字典

print(data['slideshow']['author'])

常见误区r.json() 在响应不是 JSON 时会抛异常。稳妥写法:

python
r = requests.get(url)
if r.status_code == 200:
    try:
        data = r.json()
    except ValueError:
        print('响应不是有效的 JSON:', r.text[:200])

2.5 Session:保持登录状态

有些网站登录后才能访问内部页面。登录本质上是一次 POST,成功后服务器通过 Cookie 记住你。Session 对象会自动保存和携带 Cookie:

生活化理解:普通请求像每次进小区都重新登记;Session 像办了门禁卡,刷卡即入。

python
import requests

# 创建会话
s = requests.Session()

# 第一步:登录(服务器返回的 Cookie 自动存入 session)
s.post('https://example.com/login', data={'user': 'admin', 'pwd': '123456'})

# 第二步:访问需要登录的页面(自动携带 Cookie)
r = s.get('https://example.com/dashboard')
print(r.text)

# Session 还能统一设置请求头
s.headers.update({'User-Agent': 'MyApp/1.0'})

2.6 下载文件

python
import requests

# 小文件:一次性读入内存
r = requests.get('https://example.com/logo.png')
with open('logo.png', 'wb') as f:
    f.write(r.content)  # content 是字节,text 是字符串

# 大文件:流式下载(防止撑爆内存)
with requests.get('https://example.com/big.zip', stream=True) as r:
    r.raise_for_status()  # 状态码不是 2xx 就抛异常
    with open('big.zip', 'wb') as f:
        for chunk in r.iter_content(chunk_size=8192):  # 每次 8KB
            f.write(chunk)

r.text vs r.content

属性类型适用
r.textstr(已解码)网页 HTML、JSON、文本
r.contentbytes(原始字节)图片、压缩包等二进制文件

2.7 异常处理

网络请求充满不确定性——超时、断网、DNS 失败、服务器 500……必须做异常处理:

python
import requests

try:
    r = requests.get('https://example.com/api', timeout=5)
    r.raise_for_status()  # 4xx/5xx 状态码会抛 HTTPError
    data = r.json()
except requests.exceptions.Timeout:
    print('请求超时')
except requests.exceptions.ConnectionError:
    print('网络连接失败')
except requests.exceptions.HTTPError as e:
    print(f'HTTP 错误: {e}')
except requests.exceptions.RequestException as e:
    # 上面所有异常的父类,兜底用
    print(f'请求失败: {e}')

2.8 常见误区

误区 1:不设置 timeout。

真相:默认永不超时!服务器不响应时程序会永远卡死。生产代码必须设置 timeout

误区 2:循环里反复 requests.get()

真相:每次都建立新 TCP 连接,开销大。循环请求同一个网站应该用 Session(自动连接复用)。

误区 3:用 if r.status_code == 200 判断成功。

真相:2xx 都表示成功(200 OK、201 Created、204 No Content)。更规范的写法:

python
if r.ok:  # 状态码 < 400 即为 True
    ...
# 或
r.raise_for_status()  # 失败直接抛异常

三、chardet:文件编码的"侦探"

3.1 模块简介

你是否遇到过打开一个文本文件,满屏都是"锟斤拷""烫烫烫"式的乱码?这是因为用错了编码

全世界的文本编码五花八门:UTF-8、GBK、GB2312、Big5、Shift_JIS……拿到一个来路不明的文件,怎么知道它是什么编码?

chardet(character detect,字符检测)就是干这个的——它会分析文件的字节特征,猜出最可能的编码。

bash
pip install chardet

生活化理解:chardet 像一位语言学家,拿到一段陌生文字,看看笔画特征就能判断:"这 80% 是日文,15% 可能是中文繁体"。

3.2 基本用法

python
import chardet

# 检测字节串的编码
data = b'\xc4\xe3\xba\xc3'  # GBK 编码的"你好"
result = chardet.detect(data)
print(result)
# {'encoding': 'GB2312', 'confidence': 0.99, 'language': 'Chinese'}

# 用检测到的编码解码
text = data.decode(result['encoding'])
print(text)  # 你好

返回结果的含义:

字段含义
encoding猜测的编码名称(猜不出来是 None
confidence置信度(0~1,越接近 1 越确定)
language猜测的语言

3.3 实战:读取未知编码的文件

python
import chardet

def read_any_file(path):
    """读取任意编码的文本文件"""
    with open(path, 'rb') as f:
        raw = f.read()

    result = chardet.detect(raw)
    encoding = result['encoding'] or 'utf-8'  # 猜不到就用 utf-8 兜底

    print(f"检测到编码: {encoding} (置信度: {result['confidence']:.0%})")
    return raw.decode(encoding, errors='replace')

text = read_any_file('mystery.txt')
print(text)

3.4 实战:批量转换文件编码为 UTF-8

python
import chardet
from pathlib import Path

def convert_to_utf8(src_dir):
    """把目录下所有 GBK 文件转成 UTF-8"""
    for file in Path(src_dir).glob('*.txt'):
        raw = file.read_bytes()
        result = chardet.detect(raw)

        if result['encoding'] and result['encoding'].upper() not in ('UTF-8', 'ASCII'):
            text = raw.decode(result['encoding'])
            file.write_text(text, encoding='utf-8')
            print(f'{file.name}: {result["encoding"]} → UTF-8')
        else:
            print(f'{file.name}: 已是 UTF-8,跳过')

convert_to_utf8('documents')

3.5 常见误区

误区 1:chardet 的检测结果 100% 准确。

真相:chardet 是统计猜测,不是魔法。它的准确性取决于:

  • 文本长度:文本越短越难猜。几个字节的内容可能猜错;
  • 语言特征:GBK 和 GB2312 高度相似,经常互相误判(但 GBK 兼容 GB2312,所以问题不大)。

对策:置信度低于 0.7 时要人工确认;关键业务提供编码手动指定入口。

误区 2:检测出编码后直接 decode() 就万事大吉。

真相:即使编码猜对,文件中也可能有少量损坏的字节。建议加 errors='replace' 参数,把无法解码的字节替换为 `` 而不是直接报错:

python
text = raw.decode(encoding, errors='replace')

误区 3:chardet 能检测加密或压缩的数据。

真相:chardet 只能检测纯文本的编码。ZIP、加壳数据、二进制文件(图片等)检测结果是毫无意义的。


四、psutil:系统资源的"体检医生"

4.1 模块简介

psutil(process and system utilities)是一个跨平台的系统监控库,能获取:

  • CPU 使用率、核心数、频率
  • 内存占用
  • 磁盘空间和 IO
  • 网络流量
  • 进程列表和进程详情

它统一了 Windows、Linux、macOS 的差异——同一套代码,三个系统都能跑。

bash
pip install psutil

生活化理解:psutil 就是把 Windows 的"任务管理器"和 Linux 的 top 命令搬进了 Python,而且是用代码可以读取的结构化数据。

典型应用:服务器监控告警、资源统计报表、自动清理僵死进程、运维巡检脚本。

4.2 CPU 信息

python
import psutil

# 逻辑核心数(含超线程)
print(psutil.cpu_count())          # 16

# 物理核心数
print(psutil.cpu_count(logical=False))  # 8

# CPU 使用率(百分比)
# interval=1 表示采样 1 秒,越长时间越准
print(psutil.cpu_percent(interval=1))  # 23.5

# 每个核心的使用率
print(psutil.cpu_percent(interval=1, percpu=True))
# [20.0, 35.0, 15.5, ...]

# CPU 频率(MHz)
freq = psutil.cpu_freq()
print(f'当前频率: {freq.current} MHz, 最大: {freq.max} MHz')

注意cpu_percent(interval=0)interval=None 比较的是"上次调用到现在"的平均值,第一次调用通常返回 0 或无意义。推荐显式传 interval=1

4.3 内存信息

python
import psutil

mem = psutil.virtual_memory()
print(f'总内存: {mem.total / 1024**3:.1f} GB')
print(f'已用:   {mem.used / 1024**3:.1f} GB')
print(f'可用:   {mem.available / 1024**3:.1f} GB')
print(f'使用率: {mem.percent}%')

# 交换分区(虚拟内存)
swap = psutil.swap_memory()
print(f'Swap 使用率: {swap.percent}%')

free vs available 的区别(容易混淆):

  • free:完全没被碰过的内存;
  • available实际可用内存(包括系统缓存中可以随时释放的部分)。

判断内存够不够,available,别看 free。Linux 会把空闲内存拿去做磁盘缓存,所以 free 经常很小,这是正常的。

4.4 磁盘信息

python
import psutil

# 磁盘分区
for part in psutil.disk_partitions():
    print(part.device, part.mountpoint, part.fstype)
# C:\ C:\ ntfs
# D:\ D:\ ntfs

# 某个分区的使用情况
usage = psutil.disk_usage('C:\\')
print(f'总容量: {usage.total / 1024**3:.1f} GB')
print(f'已用:   {usage.used / 1024**3:.1f} GB')
print(f'使用率: {usage.percent}%')

# 磁盘 IO 统计
io = psutil.disk_io_counters()
print(f'读取: {io.read_bytes / 1024**2:.0f} MB, 写入: {io.write_bytes / 1024**2:.0f} MB')

4.5 网络信息

python
import psutil

# 网络 IO 统计(自开机以来)
net = psutil.net_io_counters()
print(f'发送: {net.bytes_sent / 1024**2:.1f} MB')
print(f'接收: {net.bytes_recv / 1024**2:.1f} MB')

# 计算实时网速:采样两次求差值
import time
n1 = psutil.net_io_counters()
time.sleep(1)
n2 = psutil.net_io_counters()
speed = (n2.bytes_recv - n1.bytes_recv) / 1024  # KB/s
print(f'当前下载速度: {speed:.1f} KB/s')

4.6 进程管理

这是 psutil 最强大的部分:

python
import psutil

# 所有进程的 PID 列表
print(psutil.pids())

# 遍历所有进程
for proc in psutil.process_iter(['pid', 'name', 'cpu_percent']):
    print(proc.info)
# {'pid': 1, 'name': 'System', 'cpu_percent': 0.0}
# ...

# 操作单个进程
p = psutil.Process(1234)  # 按 PID 获取
print(p.name())           # 进程名
print(p.exe())            # 可执行文件路径
print(p.cwd())            # 工作目录
print(p.status())         # 运行状态(running/sleeping/zombie)
print(p.cpu_percent())    # CPU 占用
print(p.memory_info())    # 内存占用
print(p.create_time())    # 创建时间(时间戳)

# 结束进程
p.terminate()  # 温和结束(相当于点"关闭")
p.kill()       # 强制杀死(相当于"结束任务")

4.7 实战案例 1:资源监控告警

python
import psutil
import time

def monitor(threshold_cpu=90, threshold_mem=90, interval=60):
    """持续监控,资源超标时告警"""
    while True:
        cpu = psutil.cpu_percent(interval=1)
        mem = psutil.virtual_memory().percent

        if cpu > threshold_cpu:
            print(f'[告警] CPU 使用率过高: {cpu}%')
        if mem > threshold_mem:
            print(f'[告警] 内存使用率过高: {mem}%')

        time.sleep(interval)

# monitor()  # 取消注释即可启动监控

4.8 实战案例 2:揪出"资源大户"

python
import psutil

def top_memory_processes(n=10):
    """找出内存占用最高的 n 个进程"""
    procs = []
    for p in psutil.process_iter(['pid', 'name', 'memory_info']):
        try:
            procs.append(p.info)
        except (psutil.NoSuchProcess, psutil.AccessDenied):
            pass  # 进程可能刚好退出,或权限不足

    # 按内存排序
    procs.sort(key=lambda x: x['memory_info'].rss, reverse=True)

    print(f'{"PID":>8} {"内存(MB)":>10}  进程名')
    for p in procs[:n]:
        mb = p['memory_info'].rss / 1024**2
        print(f"{p['pid']:>8} {mb:>10.1f}  {p['name']}")

top_memory_processes()

4.9 实战案例 3:清理僵死进程

python
import psutil

def kill_zombies():
    """查找并清理僵尸进程"""
    for p in psutil.process_iter(['pid', 'name', 'status']):
        if p.info['status'] == psutil.STATUS_ZOMBIE:
            print(f"发现僵尸进程: {p.info['name']} (PID={p.info['pid']})")
            try:
                p.kill()
            except psutil.NoSuchProcess:
                pass

4.10 其他实用信息

python
import psutil
from datetime import datetime

# 开机时间
boot = datetime.fromtimestamp(psutil.boot_time())
print(f'开机时间: {boot}')

# 电池信息(笔记本)
battery = psutil.sensors_battery()
if battery:
    print(f'电量: {battery.percent}%, 充电中: {battery.power_plugged}')

4.11 常见误区

误区 1:遍历进程时不处理异常。

真相:进程是"活的"——你遍历的瞬间,某个进程可能刚好退出,或者你没有权限访问它。process_iter 循环中必须捕获 NoSuchProcessAccessDenied

python
for p in psutil.process_iter():
    try:
        print(p.name())
    except (psutil.NoSuchProcess, psutil.AccessDenied):
        continue

误区 2memory_info().rss 在不同系统含义完全一致。

真相:rss(常驻内存)在 Windows 和 Linux 上的统计口径略有差异。跨平台对比时知道大概量级即可,不要抠小数点。

误区 3:Windows 上想用 psutil 杀系统进程。

真相:杀进程需要相应权限。Windows 上需要"以管理员身份运行",Linux 上需要 sudo,否则会抛 AccessDenied


五、四大模块速查表

模块一句话定位安装命令核心 API
Pillow图像处理车间pip install PillowImage.open()resizethumbnailcropfilter
requests网络快递员pip install requestsgetpostSessionr.json()r.raise_for_status()
chardet编码侦探pip install chardetchardet.detect(bytes)
psutil体检医生pip install psutilcpu_percentvirtual_memorydisk_usageprocess_iter

注意导入名与安装名的差异

python
pip install Pillow    →   from PIL import Image
pip install requests  →   import requests
pip install chardet   →   import chardet
pip install psutil    →   import psutil

六、综合实战:一句话串联四大模块

最后用一个"网站截图监控"的例子,把四个模块串起来(伪代码示意):

python
import requests
import chardet
import psutil
from PIL import Image
from io import BytesIO

# 1. psutil:先检查本机资源是否健康
if psutil.virtual_memory().percent > 90:
    print('内存不足,暂停任务')

# 2. requests:下载一张网络图片
r = requests.get('https://example.com/banner.jpg', timeout=10)
r.raise_for_status()

# 3. chardet:检测一个文本接口返回内容的编码
text_resp = requests.get('https://example.com/api/notice')
encoding = chardet.detect(text_resp.content)['encoding']
notice = text_resp.content.decode(encoding or 'utf-8')

# 4. Pillow:处理下载的图片
im = Image.open(BytesIO(r.content))
im.thumbnail((400, 400))
im.save('banner_thumb.jpg')
print('任务完成:', notice)

七、小结

核心知识点一句话总结
pip第三方模块的安装入口,务必配合 venv 使用
Pillow装的是 Pillow,导入的是 PIL;thumbnail 原地改,resize 返回新对象
requests必设 timeout,用 Session 保持登录和连接复用,二进制用 content
chardet检测是"猜"不是"算",短文本不准,decode 加 errors='replace'
psutil遍历进程必捕获异常,内存看 available 别看 free

记住三句话

  1. 图像找 Pillow,上网找 requests,乱码找 chardet,监控找 psutil
  2. 所有网络请求必须设超时,所有进程遍历必须捕获异常
  3. 第三方模块虽好用,但先查标准库——能零依赖解决的,别引入新依赖。

参考说明

本文内容基于各模块官方文档及廖雪峰 Python 教程的"常用第三方模块"章节重新整理和扩充,示例代码适用于 Pillow 10+、requests 2.31+、chardet 5+、psutil 5.9+。