返回博客

45. 常用第三方模块:Pillow、requests、chardet、psutil

45. 常用第三方模块:Pillow、requests、chardet、psutil

第四十五篇:常用第三方模块——Pillow、requests、chardet、psutil

前言

Python 拥有庞大的第三方生态系统(PyPI),其中一些模块已成为事实上的行业标准。requests 是最流行的 HTTP 库,Pillow 是图像处理的标准工具,chardet 用于编码检测,psutil 提供系统监控能力。本文将逐一讲解这些实用模块的安装与核心用法。

requests —— 优雅的 HTTP 请求库

安装与环境配置

# 使用 pip 安装
pip install requests

# 如果网络较慢,可以使用国内镜像
pip install requests -i https://pypi.tuna.tsinghua.edu.cn/simple

# 验证安装
python -c "import requests; print(requests.__version__)"

GET 请求基本用法

import requests

# 基本 GET 请求
response = requests.get("https://httpbin.org/get")
print(f"状态码: {response.status_code}")   # 200
print(f"响应头 Content-Type: {response.headers['Content-Type']}")
print(f"响应内容: {response.text[:100]}...")

# 带查询参数
params = {"q": "python", "page": 1, "size": 20}
response = requests.get("https://httpbin.org/get", params=params)
print(f"完整 URL: {response.url}")
# https://httpbin.org/get?q=python&page=1&size=20

# 检查响应状态
if response.status_code == 200:
    data = response.json()  # 自动解析 JSON
    print(f"返回数据: {data['args']}")

# 使用 raise_for_status 抛出异常
try:
    response.raise_for_status()
except requests.exceptions.HTTPError as e:
    print(f"HTTP 错误: {e}")

POST 请求与表单处理

import requests

# POST 提交表单数据
form_data = {
    "username": "alice",
    "password": "secret123",
    "remember": True
}
response = requests.post(
    "https://httpbin.org/post",
    data=form_data
)
result = response.json()
print(f"接收到的表单数据: {result['form']}")

# POST 提交 JSON 数据
json_data = {
    "name": "Alice",
    "age": 28,
    "skills": ["Python", "JavaScript"]
}
response = requests.post(
    "https://httpbin.org/post",
    json=json_data  # 自动序列化 JSON 并设置 Content-Type
)
result = response.json()
print(f"接收到的 JSON 数据: {result['json']}")

# PUT / DELETE 请求
put_response = requests.put("https://httpbin.org/put", json={"action": "update"})
delete_response = requests.delete("https://httpbin.org/delete")

高级请求特性

import requests
import json

# 自定义 Header
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
    "Accept": "application/json",
    "Authorization": "Bearer your-token-here",
}
response = requests.get("https://httpbin.org/headers", headers=headers)

# Cookie 管理(Session 自动保存 cookie)
session = requests.Session()

# 第一次登录,cookie 会被 session 记住
login_response = session.post(
    "https://httpbin.org/post",
    data={"username": "alice", "password": "secret"}
)

# Session 持久化配置(一次设置,所有请求生效)
session.headers.update({"X-Custom-Header": "my-value"})
session.params.update({"api_key": "abc123"})
session.verify = True  # 启用 SSL 证书验证
session.timeout = 10   # 超时时间(秒)

# 流式下载大文件
response = requests.get("https://httpbin.org/stream/20", stream=True)
for chunk in response.iter_content(chunk_size=8192):
    if chunk:
        print(f"收到 {len(chunk)} bytes")

异常处理

import requests
import time

def fetch_with_retry(url, max_retries=3, backoff_factor=1):
    """带重试机制的请求函数"""
    for attempt in range(max_retries):
        try:
            response = requests.get(url, timeout=5)
            response.raise_for_status()
            return response
        except requests.exceptions.Timeout:
            wait_time = backoff_factor * (2 ** attempt)
            print(f"超时,{wait_time}s 后重试 ({attempt + 1}/{max_retries})...")
        except requests.exceptions.ConnectionError:
            wait_time = backoff_factor * (2 ** attempt)
            print(f"连接失败,{wait_time}s 后重试...")
        except requests.exceptions.HTTPError as e:
            print(f"HTTP 错误: {e}")
            raise
        
        time.sleep(wait_time)
    
    raise requests.exceptions.ConnectionError(f"重试 {max_retries} 次后仍然失败")

try:
    resp = fetch_with_retry("https://httpbin.org/delay/1")
    print(f"成功! 状态码: {resp.status_code}")
except Exception as e:
    print(f"最终失败: {e}")

实际用例:API 客户端封装

import requests

class APIClient:
    """通用 API 客户端封装"""
    
    def __init__(self, base_url, api_key=None, timeout=10):
        self.base_url = base_url.rstrip("/")
        self.api_key = api_key
        self.timeout = timeout
        
        self.session = requests.Session()
        self.session.headers.update({
            "Accept": "application/json",
            "Content-Type": "application/json",
        })
        if api_key:
            self.session.headers["Authorization"] = f"Bearer {api_key}"
    
    def get(self, endpoint, params=None):
        url = f"{self.base_url}/{endpoint.lstrip('/')}"
        response = self.session.get(url, params=params, timeout=self.timeout)
        response.raise_for_status()
        return response.json()
    
    def post(self, endpoint, data=None):
        url = f"{self.base_url}/{endpoint.lstrip('/')}"
        response = self.session.post(url, json=data, timeout=self.timeout)
        response.raise_for_status()
        return response.json()

client = APIClient("https://httpbin.org", api_key="demo-key")
data = client.get("/get", params={"test": "value"})
posted = client.post("/post", data={"key": "value"})

Pillow —— 图像处理库

安装

pip install Pillow

基本图像操作

from PIL import Image, ImageFilter, ImageEnhance

img = Image.open("example.jpg")
print(f"尺寸: {img.size}")          # (宽, 高)
print(f"模式: {img.mode}")          # RGB, L, P, RGBA 等
print(f"格式: {img.format}")         # JPEG, PNG 等

thumb = img.resize((200, 200))           # 强制拉伸
tthumb_fitted = img.thumbnail((200, 200))  # 保持比例

box = (100, 100, 500, 500)
cropped = img.crop(box)

rotated = img.rotate(45, expand=True)
flipped_h = img.transpose(Image.FLIP_LEFT_RIGHT)

rgb_img = img.convert("RGB")
gray_img = img.convert("L")

img.save("output.jpg", quality=90)
img.save("output.png", optimize=True)
img.save("output.webp", quality=80)

滤镜与效果

from PIL import Image, ImageFilter, ImageEnhance, ImageDraw, ImageFont

img = Image.open("example.jpg").convert("RGB")

gaussian_blur = img.filter(ImageFilter.GaussianBlur(radius=3))
sharpened = img.filter(ImageFilter.SHARPEN)
edge_detected = img.filter(ImageFilter.FIND_EDGES)
emboss = img.filter(ImageFilter.EMBOSS)

enhancer = ImageEnhance.Color(img)
colorized = enhancer.enhance(1.5)
enhancer = ImageEnhance.Brightness(img)
bright = enhancer.enhance(1.2)

watermark = Image.new("RGBA", img.size, (0, 0, 0, 0))
draw = ImageDraw.Draw(watermark)
try:
    font = ImageFont.truetype("simhei.ttf", 40)
except IOError:
    font = ImageFont.load_default()

text = "© My Website 2026"
position = (img.size[0] - 200, img.size[1] - 50)
draw.text(position, text, fill=(255, 255, 255, 128), font=font)
final = Image.alpha_composite(img.convert("RGBA"), watermark)
final_rgb = final.convert("RGB")
final_rgb.save("watermarked.jpg", quality=95)

chardet —— 编码检测

安装与基本用法

pip install chardet
import chardet

# 检测字节串的编码
sample_bytes = b'\x89PNG\r\n\x1a\nHello World!'
result = chardet.detect(sample_bytes)
print(result)
# {'encoding': 'ascii', 'confidence': 1.0, 'language': ''}

chinese_text = "你好世界!这是一个中文测试。".encode("utf-8")
result = chardet.detect(chinese_text)
print(f"编码: {result['encoding']}, 置信度: {result['confidence']:.2f}")

批量扫描目录编码

import chardet
import os

def scan_directory_encoding(dir_path):
    text_extensions = {".txt", ".csv", ".md", ".py", ".html"}
    results = []
    
    for root, _, files in os.walk(dir_path):
        for filename in sorted(files):
            if os.path.splitext(filename)[1].lower() in text_extensions:
                filepath = os.path.join(root, filename)
                with open(filepath, "rb") as f:
                    raw = f.read(10000)
                result = chardet.detect(raw)
                results.append({
                    "file": os.path.relpath(filepath, dir_path),
                    "encoding": result["encoding"],
                    "confidence": f"{result['confidence']:.0%}",
                })
    
    print(f"\n=== 编码检测报告 ===")
    for r in results:
        print(f"{r['file']}: {r['encoding']} ({r['confidence']})")
    return results

psutil —— 系统监控

安装

pip install psutil

CPU 信息

import psutil

print(f"逻辑核心数: {psutil.cpu_count()}")
print(f"物理核心数: {psutil.cpu_count(logical=False)}")

usage = psutil.cpu_percent(interval=1)
print(f"CPU 总使用率: {usage}%")

per_core = psutil.cpu_percent(interval=1, percpu=True)
print(f"各核心: {per_core}")

内存信息

import psutil

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

swap = psutil.swap_memory()
print(f"交换空间: {swap.used / 1024**3:.1f}GB ({swap.percent}%)")

net_io = psutil.net_io_counters()
print(f"网络 IO:\n  接收: {net_io.bytes_recv / 1024**2:.2f} MB\n  发送: {net_io.bytes_sent / 1024**2:.2f} MB")

进程管理

import psutil

def list_processes(top_n=10):
    processes = []
    for proc in psutil.process_iter(["pid", "name", "cpu_percent", "memory_percent"]):
        try:
            info = proc.info
            processes.append(info)
        except (psutil.NoSuchProcess, psutil.AccessDenied):
            pass
    
    processes.sort(key=lambda x: x.get("cpu_percent", 0) or 0, reverse=True)
    
    print(f"{'PID':<8} {'CPU%':>6} {'MEM%':>6} {'名称'}")
    print("-" * 40)
    for p in processes[:top_n]:
        pid = p["pid"]
        cpu = p["cpu_percent"] or 0
        mem = p["memory_percent"] or 0
        name = p["name"] or "unknown"
        print(f"{pid:<8} {cpu:>6.1f} {mem:>6.1f} {name}")

list_processes(5)

实时系统监控仪表盘

import psutil
import time

def monitor_system(duration=10, interval=1):
    print("=== 实时系统监控 ===")
    prev_net = psutil.net_io_counters()
    
    for i in range(duration // interval):
        timestamp = time.strftime("%H:%M:%S")
        cpu = psutil.cpu_percent(interval=interval)
        mem = psutil.virtual_memory()
        disk = psutil.disk_usage("/")
        
        curr_net = psutil.net_io_counters()
        down_mbps = (curr_net.bytes_recv - prev_net.bytes_recv) / 1024**2 / interval
        up_mbps = (curr_net.bytes_sent - prev_net.bytes_sent) / 1024**2 / interval
        prev_net = curr_net
        
        print(f"{timestamp} CPU:{cpu:.0f}% MEM:{mem.percent:.0f}% DISK:{disk.percent:.0f}% ↓{down_mbps:.1f}MB/s ↑{up_mbps:.1f}MB/s")
        time.sleep(interval)

# monitor_system(duration=10, interval=1)

总结

本文系统讲解了四大常用第三方模块:

  1. requests — 优雅简洁的 HTTP 请求库,支持 Session/重传/认证/文件上传
  2. Pillow — Python 标准图像处理库,resize/crop/filter/水印/验证码
  3. chardet — 自动检测文件编码,辅助批量扫描目录
  4. psutil — 跨平台系统监控(CPU/内存/磁盘/网络/进程管理)

本文是 Python 教程系列的第四十五篇。