Python-模块篇(内置模块篇)

1、系统交互

os

--路径相关

import os
#路径拼接
file_path = os.path.join('folder', 'sub', 'data.csv')

# 递归遍历所有子目录
for root, dirs, files in os.walk('./project'):
    for file in files:
        if file.endswith('.py'):
            full_path = os.path.join(root, file)
            print(f'处理: {full_path}')

# 读环境变量,不存在给默认值
db_host = os.environ.get('DB_HOST', 'localhost')

#判断文件/目录是否存在
if os.path.exists('config.ini'):
    data = open('config.ini').read()
    
# 区分文件和目录
if os.path.isfile('data.csv'):
    print('是文件')
if os.path.isdir('logs'):
    print('是目录')

# 创建单层目录
os.mkdir('new_folder')

# 多层(不存在则创建,推荐)
os.makedirs('parent/child/grandchild', exist_ok=True)

# 获取脚本所在绝对目录(注意:__file__ 在交互式环境不可用)
# __file__:当前模块
script_dir = os.path.dirname(os.path.abspath(__file__))
 
import os

# 执行命令(已经过时,推荐使用subprocess)
os.system('ls -la')         #只返回退出码,输出直接打到控制台
os.popen('ls -la').read()   #能获取输出


# ❌ 别直接删除(文件不存在会报错),先判断再删除
os.remove('maybe_not_exist.log')

 

sys

--命令行参数

# 命令行参数
# python .\debug.py --input data.csv 
print(sys.argv) #['.\\debug.py', '--input', 'data.csv']
print(sys.argv[0]) #脚本名称、.\debug.py
print(sys.argv[1]) #第一个命令行参数、--input

# 正常退出
sys.exit(0)

# 异常退出(带错误码和提示)
if not file_exists:
    sys.exit(f'错误: 文件 {filename} 不存在')
 
# 让Python能导入不在 sys.path 里的模块(#临时导入自定义模块时使用)
sys.path.append('/my/custom/libs')
import my_module  # 现在可以导入了

# 开发调试时常用:导入项目根目录的模块
sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))

 

pathlib

--路径相关

from pathlib import Path

# / 运算符拼接路径(比 os.path.join 好看)
p = Path('folder') / 'sub' / 'config.json'
print(p)  # folder/sub/config.json

# 读取文本
content = Path('data.txt').read_text(encoding='utf-8')

# 写入文本
Path('output.txt').write_text('Hello World', encoding='utf-8')

# 二进制读写
data = Path('image.png').read_bytes()
Path('copy.png').write_bytes(data)

# 遍历当前目录所有 .py 文件
for f in Path('.').glob('*.py'):
    print(f.name)

# 递归遍历所有子目录的 .log 文件
for f in Path('logs').glob('**/*.log'):  # ** 表示递归
    print(f)
# 递归创建(等同于 os.makedirs)
Path('child/grandchild').mkdir(parents=True, exist_ok=True)

p = Path('config.json')

# 判断
p.exists()      # 是否存在
p.is_file()     # 是否是文件
p.is_dir()      # 是否是目录

# 获取信息
p.stat().st_size           # 文件大小
p.stat().st_mtime          # 修改时间戳
p.resolve()                # 获取绝对路径

# 重命名/移动
p.rename('new_config.json')

# 删除
p.unlink()  # 删除文件

# 获取文件各种信息
p = Path('/home/user/data.csv')
p.name          # 'data.csv'、文件信息
p.stem          # 'data'(无扩展名)、文件名
p.suffix        # '.csv'、扩展名
p.parent        # Path('/home/user')、父文件夹
p.anchor        # '/'、根文件夹

2、日期时间与数学运算

  • 格林威治时间、纪元时间、epoch time:1970-1-1 00:00:00 UTC+0:00
  • 时间戳:从纪元时间到当前时间经过的浮点秒数

image

  •  b(底数),y(对数、多少次方),x(次方运算结果)
  • 底数b的y次方等于x

datetime

--日期格式化

from datetime import datetime, date

# 当前日期时间
now = datetime.now()          # 日期+时间、2026-07-16 14:30:25.123456
today = date.today()          # 日期、2026-07-16
current_time = datetime.now().time()  # 时间、4:30:25.123456

# 日期时间 → 字符串
now = datetime.now()
now.strftime('%Y-%m-%d %H:%M:%S')      # '2026-07-16 14:30:25'
now.strftime('%Y年%m月%d日')            # '2026年07月16日'
now.strftime('%Y-%m-%d')               # '2026-07-16'(只取日期)

# 字符串 → 日期时间
date_str = '2026-07-16 14:30:25'
dt = datetime.strptime(date_str, '%Y-%m-%d %H:%M:%S')


# 日期时间 → 时间戳
now = datetime.now()
timestamp = now.timestamp()  # 1721125825.123

# 时间戳 → 日期时间
# 类型为<class 'datetime.datetime'>
dt = datetime.fromtimestamp(timestamp) #2024-07-16 18:30:25.123000
# 常用格式速查
'''
%Y 四位年份   %y 两位年份
%m 月份       %d 日
%H 24小时制   %I 12小时制
%M 分钟       
%S 秒
%w 星期几(0-6) %A 完整星期名
'''

 

time

--休眠

import time

# 当前时间戳(秒,浮点数)
ts = time.time()  # 1721125825.123456

# 等待 2 秒
time.sleep(2)

# 时间戳 → 结构化时间(可读)
struct_time = time.localtime(1721125825) # time.struct_time(tm_year=2026...)
# 字符串 → 结构化时间(可读)
struct_time = time.strptime('2026-07-16', '%Y-%m-%d')

# 结构化时间 → 字符串
time.strftime('%Y-%m-%d %H:%M:%S', struct_time) #2026-07-16 14:30:25.123456
#  性能计时方法1:使用 time(简单)
start = time.time()
# 执行代码...
result = sum(range(1000000))
end = time.time()
print(f'耗时: {end - start:.3f}秒')

#  性能计时方法2:使用 perf_counter(更精确,推荐)
start = time.perf_counter()
# 执行代码...
end = time.perf_counter()
print(f'耗时: {end - start:.3f}秒')

 math

--数学运算

#常用数学函数
# 平方根
math.sqrt(16)      # 4.0

# 幂运算
math.pow(2, 10)    # 1024.0
2 ** 10            # 1024(内置)

# 绝对值
math.fabs(-5.2)    # 5.2
abs(-5.2)          # 5.2(内置)

# 对数
math.log(100, 10)  # 2.0(以10为底)
math.log(100)      # 4.605(自然对数,以e为底)
math.log10(100)    # 2.0

#常量
math.pi    # 3.141592653589793
math.e     # 2.718281828459045
 
#取整运算
math.ceil(3.14)    # 4(向上取整)
math.floor(3.14)   # 3(向下取整)
round(3.5)         # 4(Python 内置,四舍五入)
math.trunc(3.14)   # 3(截断小数)

 

 random

--随机数

 
import random

# 闭区间 [1, 10]
random.randint(1, 10)      # 1-10 的随机整数

# 半开区间 [1, 10)
random.randrange(1, 10)    # 1-9 的随机整数
random.randrange(1, 10, 2)  # 1,3,5,7,9 中随机、间隔2

# [0.0, 1.0) 的随机浮点数
random.random()      # 0.3746
# [1.5, 5.5) 的随机浮点数
random.uniform(1.5, 5.5)  # 3.218


items = ['apple', 'banana', 'cherry', 'date']
# 随机选一个
random.choice(items)  # 'banana'
# 随机选多个(2个、不重复)
random.sample(items, 2)  # ['apple', 'date']
# 随机选多个(5个、可重复)
random.choices(items, k=5)  # ['apple', 'banana', 'apple', 'date', 'cherry']
 
# 设置种子后,每次运行结果相同
random.seed(42)
print(random.randint(1, 100))  #每次运行都是82
print(random.randint(1, 100))  #每次运行都是15

# 常用于测试,让随机结果可复现

 

3、数据处理

  • 序列化:Python对象<--->特定的数据格式(比如json)
json
import json

# Python 字典 → JSON 字符串
data = {'name': '张三', 'age': 25, 'score': 95.5}
json_str = json.dumps(data, ensure_ascii=False)  
# '{"name": "张三", "age": 25, "score": 95.5}'

# JSON 字符串 → Python 字典
json_str = '{"name": "李四", "age": 30}' #字符串必须用双引号
data = json.loads(json_str)  # {'name': '李四', 'age': 30}
data = {'name': '张三', 'age': 25}

# 写入文件,ensure_ascii=False 保留中文,
with open('data.json', 'w', encoding='utf-8') as f:
    json.dump(data, f, ensure_ascii=False, indent=2) 


# 读取文件
with open('data.json', 'r', encoding='utf-8') as f:
    data = json.load(f)
csv
import csv

#  读取 CSV(推荐用 DictReader),读成字典列表(有表头,最推荐)
with open('users.csv', 'r', encoding='utf-8') as f:
    reader = csv.DictReader(f)
    for row in reader:
        print(row['name'], row['age'])
# 每行是一个 OrderedDict,用列名访问
# 写入 CSV(推荐用 DictWriter),有表头写入
data = [
    {'name': '张三', 'age': 25, 'city': '北京'},
    {'name': '李四', 'age': 30, 'city': '上海'}
]

with open('output.csv', 'w', newline='', encoding='utf-8') as f:
    fieldnames = ['name', 'age', 'city']
    writer = csv.DictWriter(f, fieldnames=fieldnames)
    
    writer.writeheader()  # 写入表头
    writer.writerows(data)  # 写入所有行

pickle

--序列化

import pickle

# 保存任意对象到文件
data = {
    'name': '张三',
    'scores': [95, 88, 92],
    'config': {'debug': True}
}

with open('data.pkl', 'wb') as f:
    pickle.dump(data, f)

# 加载对象
with open('data.pkl', 'rb') as f:
    loaded = pickle.load(f)  # 恢复为 Python 对象
# 对象 → 字节串,保存对象到字节串
data = {'name': '张三'}
bytes_data = pickle.dumps(data)

# 字节串 → 对象
loaded = pickle.loads(bytes_data)

# 跨语言传输不要用 pickle,用 JSON
# 不要从不可信来源加载 pickle,可能执行恶意代码
# 打开的文件对象、网络连接等无法序列化

hashlib

--哈希值

 
import hashlib

# MD5(最常用,但不安全,仅用于校验)
text = 'hello world'
md5_hash = hashlib.md5(text.encode('utf-8')).hexdigest()
# '5eb63bbbe01eeed093cb22bb8f5acdc3'

# SHA-256(更安全,推荐)
sha256_hash = 
hashlib.sha256(text.encode('utf-8')).hexdigest() #'b94d27b9934d3e08a52e52d7da7dabfac484efe3.....'
 
base64
--二进制数据
 
import base64
#编码过程:字符串-->字节串-->二进制字节串-->二进制字符串
#解码过程:二进制字符串-->字节串-->字符串

# 字符串 → Base64 编码(二进制数据)
text = 'Hello World' #字符串

#转换为字节串、b'Hello World'
text_bytes = text.encode('utf-8')

#转换二进制为字节串、b'SGVs....'
b64_bytes = base64.b64encode(text_bytes)

#转换为二进制字符串、'SGVs....'
b64_str = b64_bytes.decode('utf-8') 

# Base64 → 字符串解码
# b'Hello World'、转换为字节串
decoded_bytes = base64.b64decode(b64_str) 

# 'Hello World'、转换为字符串
decoded_text = decoded_bytes.decode('utf-8')  
import base64
import json
# 读取图片,转成 Base64 with open('avatar.jpg', 'rb') as f: img_bytes = f.read() img_b64 = base64.b64encode(img_bytes).decode('utf-8') # 嵌入 HTML(可直接显示图片) html_img = f'<img src="data:image/jpeg;base64,{img_b64}">' # 嵌入 json data = {'avatar': img_b64} json.dumps(data) # 可以传输图片了

re

--正则 

 
import re

# search:查找第一个匹配
text = '我的电话是 138-1234-5678,另一个是 139-9876-5432'
match = re.search(r'\d{3}-\d{4}-\d{4}', text)
if match:
    print(match.group())  #'138-1234-5678'、
#group()获取匹配的全部内容
# match:从开头匹配(相当于 ^pattern) result = re.match(r'\d{3}', '123-456-789') print(result.group()) # '123' result = re.match(r'\d{3}', 'abc123') # None(不匹配) # fullmatch:必须完全匹配 if re.fullmatch(r'\d{11}', '13812345678'): print('是11位数字') #是11位数字 text = '苹果: 5元, 香蕉: 3元, 橙子: 4元' # findall:返回所有匹配字符串列表 prices = re.findall(r'\d+', text) # ['5', '3', '4'] # finditer:返回迭代器(处理大量匹配时省内存) for match in re.finditer(r'(\w+): (\d+)元', text): print(match.group()) print(f'{match.group(1)} = {match.group(2)}')
#group(1)表示第一个分组 # 苹果 = 5 # 香蕉 = 3 # 橙子 = 4
 
import re


text = '2026-07-16, 2025-12-31'

# 替换所有日期格式
new_text = re.sub(r'(\d{4})-(\d{2})-(\d{2})', r'\1年\2月\3日', text)
# 结果:'2026年07月16日, 2025年12月31日'

# 如果同一个正则多次使用,先编译,可提高性能
phone_pattern = re.compile(r'1[3-9]\d{9}')

# 多次调用、比每次写字符串快
phone_pattern.search(text1)
phone_pattern.findall(text2)

text = '<div>内容1</div><div>内容2</div>'

# 贪婪匹配(默认):匹配最长
re.search(r'<div>.*</div>', text).group()
# '<div>内容1</div><div>内容2</div>'(全部)

# 非贪婪匹配:匹配最短(问号表示非贪婪匹配)
re.search(r'<div>.*?</div>', text).group()
# '<div>内容1</div>'(只匹配第一个)

4、高级数据结构

collections

--特殊容器

from collections import Counter

# 统计列表元素出现次数
colors = ['red', 'blue', 'red', 'green', 'blue', 'red']
cnt = Counter(colors)
print(cnt)  # Counter({'red': 3, 'blue': 2, 'green': 1})

# 统计字符串字符出现次数
cnt = Counter('hello world')
print(cnt.most_common(3))  #3表示列出3个元素,从多到少
# [('l', 3), ('o', 2), ('h', 1)],

# 常用操作
cnt['red']          # 3(获取次数)
cnt['yellow']       # 0(不存在的返回0)
cnt['blue'] += 1    # 增加计数
cnt['red'] -= 1     # 减少计数
cnt['red'] = 0      # 置零(但键还在)
del cnt['green']    # 删除键
from collections import defaultdict #带默认值的字典、省去判断是否存在
from collections import deque #双端队列(高效列表操作、适合频繁左操作)
from collections import namedtuple #带名字的元组

 

itertools
--迭代器工具
 
from itertools import chain #拼接多个可迭代对象
from itertools import product #笛卡尔积(嵌套循环的替代)
from itertools import permutations #排列(有序)
from itertools import combinations #组合(无序)
from itertools import cycle #无限循环
from itertools import repeat #重复值
 

 functools

--高阶函数

 
from functools import lru_cache #缓存函数结果(最常用!)

# 斐波那契数列(递归,有重复计算)
@lru_cache(maxsize=128)  # 最多缓存128个结果
def fib(n):
    if n < 2:
        return n
    return fib(n-1) + fib(n-2)

# 第一次计算 fib(40) 耗时,后续调用瞬间返回
print(fib(40))  # 102334155
print(fib(40))  # 立即返回缓存结果

# 查看缓存信息
print(fib.cache_info())  

# CacheInfo(hits=1, misses=40, maxsize=128, currsize=41) # 清除缓存 fib.cache_clear()
 
from functools import partial #固定部分参数(偏函数)
from functools import wraps #保留被装饰函数的元信息
from functools import reduce #累计计算

5、配置文件

# config.ini
[database]
host = localhost
port = 3306
user = root
password = 123456

[redis]
host = 127.0.0.1
port = 6379
db = 0

[app]
debug = true
log_level = INFO
configparser
--处理.ini配置文件
import configparser

# 创建解析器
config = configparser.ConfigParser()

# 读取配置文件、最常用
config.read('config.ini', encoding='utf-8')

# 获取配置值(必须指定 section 和 key)
db_host = config.get('database', 'host')        # 'localhost'
db_port = config.getint('database', 'port')     # 3306(自动转 int)
debug = config.getboolean('app', 'debug')       # True(自动转 bool)
log_level = config.get('app', 'log_level')      # 'INFO'

# 获取所有 sections
sections = config.sections()  # ['database', 'redis', 'app']

# 检查 section 或 key 是否存在
if config.has_section('database'):
    if config.has_option('database', 'host'):
        host = config.get('database', 'host')
 

 argparse

--处理命令行参数

import argparse

parser = argparse.ArgumentParser()

# 位置参数:必须按顺序传
parser.add_argument('input', help='输入文件')
parser.add_argument('output', help='输出文件')

# 可选参数:用 - 或 -- 开头,不必须
parser.add_argument('--verbose', '-v', action='store_true', help='显示详细输出')
parser.add_argument('--config', '-c', help='配置文件路径')
parser.add_argument('--count', '-n', type=int, default=1, help='重复次数')

args = parser.parse_args()

print(f'输入文件: {args.input}')
print(f'输出文件: {args.output}')
if args.verbose:
    print('显示详细输出')
if args.config:
    print(f'配置文件路径: {args.config}')
print(f'重复次数: {args.count}')

# 运行示例:
# python script.py in.txt out.txt -v -c config.ini -n 5
# 输出结果
输入文件: in.txt
输出文件: out.txt
args.verbose为True,显示详细输出
配置文件路径: config.ini
重复次数: 5

1、action='store_true'、布尔开关:传了就True

2、type=int:自动转换为int

3、default=1:默认值为1

 

6、日志与调试

logging

--记录日志

  • 日志等级:DEBUG、INFO、WARNING、ERROR、CRITICAL
    • 默认级别是 WARNING,只显示 WARNING 及以上
  • 四大组件:logger、handler、formatter(格式化)、filter(过滤)
    • logger 生成日志,handler将日志分发并输出到指定目的地
import logging

# 创建 logger
logger = logging.getLogger('my_app')
logger.setLevel(logging.DEBUG)

# 控制台 handler
console_handler = logging.StreamHandler()  #输出到流、默认是控制台
console_handler.setLevel(logging.INFO) #只输出INFO级及以上的日志
console_format = logging.Formatter('%(levelname)s - %(message)s') 
console_handler.setFormatter(console_format)

# 文件 handler
file_handler = logging.FileHandler('app.log', encoding='utf-8')
file_handler.setLevel(logging.DEBUG)
#formatter file_format =
logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
file_handler.setFormatter(file_format)
# 添加 handler logger.addHandler(console_handler) logger.addHandler(file_handler) # 使用 logger.debug('调试信息') # debug级别的日志只写入文件 logger.info('程序启动') # 控制台 + 文件 logger.error('连接失败') # 控制台 + 文件
import logging
from logging.handlers import RotatingFileHandler

# 基础配置(输出到控制台)
# 实际是对root logger进行配置
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s'
)

# 使用
logging.debug('调试信息')     # 不会显示(级别低于 INFO)
logging.info('程序启动')      
# ✅ 显示、2026-07-17 13:44:52,671 - INFO - 程序启动
logging.warning('磁盘空间不足') # ✅ 显示
logging.error('连接失败')     # ✅ 显示
logging.critical('系统崩溃')  # ✅ 显示

#其它补充
#文件轮转 handler:单个文件最大 10MB,保留 3 个备份
handler = RotatingFileHandler(
    'app.log',
    maxBytes=10 * 1024 * 1024,  # 10MB
    backupCount=3,              # 保留 3 个备份
    encoding='utf-8'
)

# ✅ 使用自己的 logger
logger = logging.getLogger(__name__)  # 每个模块独立的 logger

# ❌ 日志信息用 f-string 拼接(每次都计算)
logger.debug(f'用户: {user}')  # 即使级别不显示也会计算

# ✅ 用 %s 占位符(延迟计算,性能更好)
logger.debug('用户: %s', user)

traceback

--记录堆栈

 
import traceback

def func_a():
    func_b()

def func_b():
    traceback.print_stack() #打印堆栈、输出到控制台(不抛出异常)
    print('继续执行...')

func_a()
 
try:
    1 / 0
except ZeroDivisionError:
     # 获取异常堆栈字符串(用于日志记录)
    stack_str = traceback.format_exc() 
    print('错误堆栈:')
    print(stack_str)

warning

--发出警告

 
import warnings

# 发出警告、最常用(不影响程序运行)
warnings.warn('这个功能即将弃用,请使用新接口')
warnings.warn('配置文件格式不正确,使用默认值')

print('程序继续运行...')  # 警告不会中断程序
 
posted @ 2026-07-14 10:34  Fēngwèi  阅读(6)  评论(0)    收藏  举报