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
- 时间戳:从纪元时间到当前时间经过的浮点秒数

- 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 = |
|
|
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 |
|
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'、 |
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()) |
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 --记录日志 |
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) |
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('程序继续运行...') # 警告不会中断程序 |
本文来自博客园,作者:Fēngwèi,转载请注明原文链接:https://www.cnblogs.com/fengwei-blogs/p/21439261

浙公网安备 33010602011771号