Python常见模块及其用法示例详解

前言

同样是标准库模块,真正的差别不在名字认不认识,而在参数怎么写、边界怎么处理、异常往哪抛 。比如 json.dumps 的 ensure_ascii 默认是 True;csv 在 Windows 上写文件不加 newline="" 就多空行;subprocess.run 默认不检查子进程的返回码。这些都是文档里写着、但第一次用绝不会注意到的细节。

本文挑七个最常用的标准库模块,把关键函数签名、返回类型和易错边界逐条过一遍。所有示例只依赖标准库,Python 3.8 及以上可运行;涉及更新版本才有的接口会单独标注。

需要先更正一个常见说法:「常见模块」不等于「必须全部掌握」。真正的高频面很窄------文件、JSON、时间、正则、计数、日志、命令行,覆盖日常脚本九成以上的需求。剩下的按需再学。

一、pathlib:用对象表示路径

pathlib.Path 把路径封装成对象,拼接用 / 运算符,比字符串相加安全(自动处理分隔符)。

python 复制代码
# 适用于 Python 3.8+

from pathlib import Path



root = Path("data")

target = root / "reports" / "2024.txt"



target.parent.mkdir(parents=True, exist_ok=True)   # 递归建目录

target.write_text("hello\n", encoding="utf-8")

print(target.read_text(encoding="utf-8"))          # hello

print(target.name, target.stem, target.suffix)     # 2024.txt 2024 .txt

关键方法一览:

方法 签名要点 返回

|-------------|-------------------------------------------------------|-------|
| read_text | read_text(encoding=None, errors=None, newline=None) | str |

|--------------|--------------------------------------------------------------|--------|
| write_text | write_text(data, encoding=None, errors=None, newline=None) | 写入的字符数 |

|--------------|-----|---------|
| read_bytes | 无参数 | bytes |

|---------|----------------------------------------------------|--------|
| mkdir | mkdir(mode=0o777, parents=False, exist_ok=False) | None |

|--------|-----------------------------------------------------------------|-----|
| glob | glob(pattern, *, case_sensitive=None, recurse_symlinks=False) | 生成器 |

|---------|---------------------------------------------------|-----|
| rglob | rglob(pattern, ...),等价于 glob("**/" + pattern) | 生成器 |

三点提醒。第一,read_text 的 encoding 默认是 None,表示用平台默认编码------Windows 上通常不是 UTF-8,跨平台读中文文件几乎必乱码,总是显式写 encoding="utf-8" 。第二,Path 的实例方法 glob 返回的是生成器 ,要列表得自己 list()。第三,mkdir 默认 parents=False,父目录不存在会抛 FileNotFoundError;递归创建要传 parents=True。

rglob 的 **/ 能匹配零层目录,所以它会把当前目录下的文件也算进去,不只是子目录里的。

python 复制代码
# 适用于 Python 3.8+

from pathlib import Path



for p in sorted(Path(".").rglob("*.py"))[:3]:

    print(p, p.stat().st_size)

二、json 与 csv:结构化数据的两条路

json 模块四个函数,名字里的 s 表示 string,没有 s 表示操作文件对象:

函数 作用 返回

|------------------------|--------------|-------|
| json.dumps(obj, ...) | 对象转 JSON 字符串 | str |

|-----------------|-------------|----------|
| json.loads(s) | JSON 字符串转对象 | object |

|---------------------------|----------|--------|
| json.dump(obj, fp, ...) | 对象写入文件对象 | None |

|-----------------|-----------|----------|
| json.load(fp) | 从文件对象读出对象 | object |

python 复制代码
# 适用于 Python 3.8+

import json



payload = {"name": "张三", "scores": [90, 85], "active": True}

text = json.dumps(payload, ensure_ascii=False, indent=2)

print(text)

print(json.loads(text)["scores"][0])   # 90

ensure_ascii=False 控制是否把非 ASCII 字符转成 \uXXXX 转义。默认 True,中文会被转义成一串码点,虽然解析结果一样,但文件基本没法读。indent=2 用来生成方便人看的缩进格式。

一个必须知道的边界:JSON 的键只能是字符串 。把 {1: "a"} 传给 json.dumps,默认会抛 TypeError(skipkeys=True 可改成跳过)。反过来,json.loads 得到的对象里,数字键永远不存在------因为它们原本就是字符串。

csv 模块处理逗号分隔文本。读文件建议显式传 encoding;写文件必须传 newline="":

python 复制代码
# 适用于 Python 3.8+

import csv



rows = [["名字", "分数"], ["张三", "90"], ["李四", "85"]]

with open("scores.csv", "w", newline="", encoding="utf-8") as f:

    writer = csv.writer(f)

    writer.writerow(rows[0])

    writer.writerows(rows[1:])



with open("scores.csv", newline="", encoding="utf-8") as f:

    for row in csv.DictReader(f):

        print(row["名字"], row["分数"])

newline="" 的作用是禁止 Python 再做换行转换 ,由 csv 模块自己控制行尾。省掉它,Windows 上每行之间会多出一个空行。csv.DictReader 把首行当表头,后续行以字典形式给出;对应的 csv.DictWriter 需要先用 fieldnames 参数指定列。

三、容器、统计与日期时间

collections 与 statistics:容器与统计

collections.Counter 做计数,most_common(n=None) 返回按次数降序的列表:

python 复制代码
# 适用于 Python 3.8+

from collections import Counter, deque, namedtuple



words = "the quick the lazy the".split()

c = Counter(words)

print(c["the"])                 # 3

print(c.most_common(1))         # [('the', 3)]

print(c["missing"])             # 0,不存在的键返回 0 而不是 KeyError

注意最后一行:Counter 访问不存在的键返回 0 而不抛异常 ,这和普通 dict 的 [] 行为不同。这很方便(省掉判断),也很危险(拼错键名不会报错,只是静默得到 0)。

namedtuple 生成带字段名的元组类,访问用属性而不是下标:

python 复制代码
# 适用于 Python 3.8+

from collections import namedtuple



Point = namedtuple("Point", ["x", "y"])

p = Point(3, 4)

print(p.x, p[0], tuple(p))      # 3 3 (3, 4)

statistics 模块提供基础统计量,函数都很短:

函数 签名 说明

|--------|--------------|------|
| mean | mean(data) | 算术平均 |

|---------|-----------------------------|-------------|
| fmean | fmean(data, weights=None) | 用浮点累加,适合大样本 |

|----------|----------------|-----|
| median | median(data) | 中位数 |

|--------|--------------|------------|
| mode | mode(data) | 众数;无重复值时报错 |

|---------|--------------------------|---------------|
| stdev | stdev(data, xbar=None) | 样本标准差(分母 n-1) |

|----------|-------------------------|-------------|
| pstdev | pstdev(data, mu=None) | 总体标准差(分母 n) |

python 复制代码
# 适用于 Python 3.8+

import statistics



data = [2, 4, 4, 4, 5, 5, 7, 9]

print(statistics.mean(data))     # 5

print(statistics.median(data))   # 4.5

print(statistics.mode(data))     # 4

stdev 与 pstdev 的区别值得记住:前者是样本 标准差,后者是总体标准差,分母不同,结果在小样本下差别明显。选错不会报错,只会算出一个「看起来对」的数。

datetime:日期时间的三件事

datetime 模块的核心类型是 date、time、datetime 和 timedelta。

python 复制代码
# 适用于 Python 3.8+

from datetime import datetime, timedelta



now = datetime.now()

print(now.strftime("%Y-%m-%d %H:%M:%S"))       # 2026-10-07 12:00:00 格式



later = now + timedelta(days=7, hours=3)

print(later > now)                             # True

print((later - now).total_seconds())           # 608400.0

timedelta 的构造参数是 days、seconds、microseconds、milliseconds、minutes、hours、weeks,全部是关键字参数 ,写 timedelta(7, 3) 会得到 7 天 3 秒而不是 7 天 3 小时------参数是按顺序填 days, seconds 的,这个错误非常常见。

解析字符串用 datetime.strptime(date_string, format),格式化用实例方法 dt.strftime(format)。常用格式符:

格式符 含义 示例输出

|------|------|------|
| %Y | 四位年份 | 2026 |

|------|------|----|
| %m | 两位月份 | 10 |

|------|-----|----|
| %d | 两位日 | 07 |

|----------------|---------------|----------|
| %H %M %S | 时、分、秒(24 小时制) | 12 00 00 |

|------|------------|--------|
| %f | 微秒,补零到 6 位 | 000000 |

|------|--------|-------|
| %z | UTC 偏移 | +0800 |

|------|--------------|--------|
| %A | 星期全名(依赖区域设置) | Monday |

|------|---------|-----|
| %j | 一年中的第几天 | 280 |

要注意 %Y 和 %y 不是一回事 :%y 是两位年份,解析时会有世纪推断问题。另外从 3.13 起,只含「日」不含「年」的格式串调用 strptime 会发出 DeprecationWarning ,官方计划在后续版本把它变成错误或改默认年。从 3.12 起 utcnow() 与 utcfromtimestamp() 已弃用,应改用带时区参数的写法。

naive 与 aware 的区分必须提一句:没有 tzinfo 的 datetime 叫 naive,有 tzinfo 的叫 aware,两者相减会抛 TypeError 。带时区用 zoneinfo 模块,它是 Python 3.9 新增的。

四、文本、校验、命令行与日志

re 与 hashlib:文本与校验

re 的常用入口是四个函数和一个类方法:

python 复制代码
# 适用于 Python 3.8+

import re



text = "订单号 A123,订单号 B456"

print(re.findall(r"[A-Z]\d{3}", text))     # ['A123', 'B456']

print(re.search(r"\d+", text).group())     # 123

print(re.sub(r"\d", "#", text))            # 订单号 A###,订单号 B###

三条实践建议。第一,正则一律用原始字符串 r"...",否则 \d、\n 会先被字符串字面量解释一遍。第二,re.search 返回的是 Match 对象或 None,必须先判空 再取 .group(),否则 None.group() 直接 AttributeError。第三,同一个正则重复使用时用 re.compile(pattern) 编译成对象,代码更清晰。

hashlib 做摘要(哈希):

python 复制代码
# 适用于 Python 3.8+

import hashlib



digest = hashlib.sha256(b"hello").hexdigest()

print(len(digest), digest[:16])       # 64 2cf24dba5fb0a30e

hexdigest() 返回十六进制字符串(64 个字符),digest() 返回原始字节。要更新已有摘要对象用 .update(data),参数必须是 bytes,不是 str------传字符串会抛 TypeError。

算大文件的摘要时不要一次性读进内存。Python 3.11 起提供了 hashlib.file_digest(fileobj, digest, /):

python 复制代码
# 适用于 Python 3.11+;3.11 以下需手动分块读出后 update

import hashlib



with open("big.bin", "rb") as f:

    print(hashlib.file_digest(f, "sha256").hexdigest())

必须强调:哈希不是加密。 SHA-256 这类摘要算法是单向的、不可逆的,适合做完整性校验;存密码要用专门的口令派生函数 ,比如 hashlib.scrypt,而不是直接对密码哈希一次。不过 sha256 也是 hashlib.new 里名字最常用的那个,别把它当加密算法描述。

argparse 与 logging:程序的两个门面

argparse 用来解析命令行参数:

python 复制代码
# 适用于 Python 3.8+

import argparse





def build_parser():

    parser = argparse.ArgumentParser(description="示例工具")

    parser.add_argument("path", help="要处理的文件路径")

    parser.add_argument("--times", type=int, default=1, help="重复次数")

    parser.add_argument("--verbose", action="store_true", help="输出详细信息")

    return parser





def main():

    args = build_parser().parse_args()

    if args.verbose:

        print(f"路径={args.path} 次数={args.times}")





if __name__ == "__main__":

    main()

add_argument 里没有前缀的 "path" 是位置参数 (必填),带 -- 的是可选参数 。type=int 会在解析时做转换------这是 argparse 比手工读 sys.argv 强的地方。action="store_true" 表示出现即为真,不需要跟值。

logging 比到处 print 更适合真实程序:

python 复制代码
# 适用于 Python 3.8+

import logging



logging.basicConfig(

    level=logging.INFO,

    format="%(asctime)s %(levelname)s %(name)s %(message)s",

)

log = logging.getLogger(__name__)



log.info("开始处理")

log.warning("配置项缺失,使用默认值")

级别从低到高是 DEBUG、INFO、WARNING、ERROR、CRITICAL。basicConfig 只对「根记录器」生效,而且重复调用只有第一次起作用 ------如果你在多个模块里各写一次 basicConfig,后面那些会被静默忽略。这是排查「日志格式没变」问题时最容易忽略的一点。

另外,getLogger(__name__) 用模块名作记录器名,日志里就能看出每条来自哪个模块,这几乎是无成本的收益。

常见坑点

1. read_text 不写 encoding

❌ Path("a.txt").read_text() 在 Windows 上按默认编码(通常 GBK)读 UTF-8 文件,中文变乱码或直接 UnicodeDecodeError。 ✅ 显式写 read_text(encoding="utf-8")。

2. timedelta 参数顺序记错

❌ timedelta(7, 3) 以为是 7 天 3 小时,实际是 7 天 3 秒 。 ✅ 全部用关键字:timedelta(days=7, hours=3)。

3. mkdir 忘了 parents=True

❌ Path("a/b/c").mkdir() 在 a 不存在时抛 FileNotFoundError。 ✅ Path("a/b/c").mkdir(parents=True, exist_ok=True)。

4. re.search 结果不判空

❌ re.search(r"\d+", text).group(),没匹配到时对 None 调用 .group() 报 AttributeError。 ✅ 先 m = re.search(...),if m: 再取 m.group()。用 re.findall 时也不用判空,它返回空列表。

5. Counter 掩盖键名拼写错误

❌ 用 Counter 统计后写 c["frequncy"](拼错),拿到 0 而不是报错,统计结果静默出错。 ✅ 键名集中定义成常量;需要严格性时用 dict 或先 set(c.keys()) 校验。

6. csv 写入不加 newline=""

❌ open(path, "w", encoding="utf-8") 后直接写,Windows 上每行之间出现空行。 ✅ open(path, "w", newline="", encoding="utf-8")。

7. hashlib 传了字符串

❌ hashlib.sha256("hello") 抛 TypeError,因为摘要函数只接受字节串。 ✅ hashlib.sha256("hello".encode("utf-8")) 或直接写 b"hello"。

8. 在多个模块里重复调用 basicConfig

❌ 每个模块都写一次 logging.basicConfig(...),只有第一次生效,后面的格式设置被忽略。 ✅ 只在程序入口调用一次,其他模块用 logging.getLogger(__name__) 取记录器。

总结

模块 核心函数 最容易踩的边界

|-----------|--------------------------------------|--------------------|
| pathlib | read_text / write_text / mkdir | 编码与 parents=True |

|--------|-------------------|--------------------------|
| json | dumps / loads | ensure_ascii 默认 True |

|-------|-------------------------|-------------------------|
| csv | writer / DictReader | Windows 必须 newline="" |

|---------------|------------------------------------|------------------|
| collections | Counter / deque / namedtuple | Counter 缺键返回 0 |

|--------------|-----------------------------|-------------------------|
| statistics | mean / median / stdev | stdev 与 pstdev 分母不同 |

|------------|---------------------------------------|--------------------|
| datetime | strptime / strftime / timedelta | naive 与 aware 不能相减 |

|-----------|------------------------|--------|
| hashlib | sha256 / hexdigest | 只接受字节串 |

|-----------|-----------------------------|---------------------|
| logging | basicConfig / getLogger | basicConfig 只生效一次 |

这八个模块的共同点是:接口简单,边界刁钻 。参数少到几乎不用查文档就能写出来,但默认值的选择往往和直觉相反------ensure_ascii 默认转义中文、subprocess.run 默认不检查返回码、basicConfig 默认只生效一次。养成「用之前扫一眼签名和默认值」的习惯,比记住任何一个具体结论都有用。

相关推荐
databook2 小时前
Scikit-Learn实战:5步搞定PCA降维
python·机器学习·scikit-learn
程序员-Benothing2 小时前
Linux文本排序统计命令:sort、uniq、wc、cut、tr实战
java·开发语言·算法
CRMEB2 小时前
前后端技术栈全面换代!CRMEB 多商户(Java)v3.0更新预告
java·开发语言
溪语流沙3 小时前
【Web全栈进阶】JWT无状态认证:签发、校验、刷新
前端·git·python·github
JQLvopkk3 小时前
HslCommunication,一个工具测遍所有 PLC
开发语言·人工智能·c#·交互
reasonsummer3 小时前
【办公类-112-08】20261009园园通信息合并配学号拆班(数据更新,用年月日期区分版本)
python
阿狗童鞋3 小时前
Python爬虫进阶实战指南
开发语言·爬虫·python
中原第一高手3 小时前
fofatoto 1.8.0 发布:启动即知新版本、中文进度面板与更干净的 Web 日志
python·网络安全·开源·资产测绘·fofa
下页、再停留3 小时前
【C#桌面客户端系列学习-7】数据查询展示
开发语言·c#·visual studio