Python常用代码大全:文件操作、数据处理与网络请求核心模板
1. 项目概述为什么需要一份“常用代码大全”刚接触Python那会儿我经常陷入一种循环明明上周才写过处理CSV文件的代码这周要用时又得去翻文档或者搜博客。后来项目做多了发现很多代码片段就像螺丝刀、扳手一样是解决日常开发问题的“标准件”。把这些“标准件”整理好随时取用能极大提升编码效率和代码质量。这份“Python常用代码大全”就是基于这个想法诞生的它不是一本教科书而是一个工具箱里面装的是我这些年写Python时那些反复被验证、打磨过的代码片段。这份大全面向的是所有Python使用者无论你是刚入门的新手想快速找到能跑起来的示例还是有一定经验的开发者希望在处理文件、数据、网络请求等常见任务时能有个可靠、高效的参考模板。它的核心价值在于“即用性”和“可靠性”。每一段代码都力求简洁、清晰并附上了关键的解释和避坑提示让你不仅能复制粘贴更能理解背后的逻辑避免踩进我当年踩过的那些坑里。接下来我们就打开这个工具箱看看里面都有哪些趁手的“家伙事儿”。2. 核心工具箱文件与数据操作篇文件读写和数据解析是编程中最基础也最高频的操作。这部分代码的健壮性和效率直接影响到整个程序的稳定性。2.1 文件读写安全与高效并重文件操作最怕两件事一是忘记关闭文件导致资源泄露二是编码问题导致乱码。现代Python的with语句和明确的编码声明是解决这两个问题的利器。基础文件读写模板# 安全地读取文本文件推荐 file_path ‘data.txt’ try: with open(file_path, ‘r’, encoding‘utf-8’) as f: content f.read() # 或者按行读取: lines f.readlines() except FileNotFoundError: print(f“文件 {file_path} 不存在”) except UnicodeDecodeError: print(“文件编码可能不是utf-8请尝试 ‘gbk’ 或 ‘latin-1’”) # 使用 ‘with’ 语句文件会在代码块结束后自动关闭无需手动调用 f.close() # 安全地写入文本文件 output_path ‘result.txt’ data_to_write “这是要写入的内容\n第二行” with open(output_path, ‘w’, encoding‘utf-8’) as f: f.write(data_to_write) # 模式 ‘w’ 会覆盖原文件若要追加请使用 ‘a’注意encoding‘utf-8’在大多数情况下是安全的但处理Windows系统生成的或某些旧文件时可能会遇到gbk编码。一个实用的技巧是使用chardet库需安装先探测编码import chardet; with open(file, ‘rb’) as f: encoding chardet.detect(f.read())[‘encoding’]。处理大型文件的技巧一次性读入大文件会消耗大量内存。正确的做法是流式读取。# 逐行处理大文件内存友好 big_file_path ‘huge_log.log’ with open(big_file_path, ‘r’, encoding‘utf-8’) as f: for line in f: # 这里是一次读一行到内存 process(line) # 对每一行进行处理 # 如果行也很大可以按指定大小读取 chunk_size 1024 * 1024 # 每次读取1MB with open(big_file_path, ‘rb’) as f: # 使用二进制模式避免编码问题 while True: chunk f.read(chunk_size) if not chunk: break process_chunk(chunk)2.2 JSON与CSV结构化数据处理的左膀右臂JSON和CSV是数据交换的两种通用格式。Python标准库中的json和csv模块让处理它们变得非常简单。JSON序列化与反序列化import json # Python对象 - JSON字符串 - 文件 data { “name”: “张三”, “age”: 30, “skills”: [“Python”, “数据分析”], “is_employed”: True } json_str json.dumps(data, ensure_asciiFalse, indent2) # 美化输出中文正常显示 with open(‘data.json’, ‘w’, encoding‘utf-8’) as f: f.write(json_str) # 或者直接用 json.dump(data, f, ensure_asciiFalse, indent2) # 文件 - JSON字符串 - Python对象 with open(‘data.json’, ‘r’, encoding‘utf-8’) as f: loaded_data json.load(f) print(loaded_data[‘name’]) # 输出张三实操心得ensure_asciiFalse是处理中文等非ASCII字符的关键参数务必加上。indent参数让生成的JSON文件易于阅读但在生产环境传输时为了节省空间通常会省略。CSV文件读写处理CSV时使用csv.DictReader和csv.DictWriter会让代码更清晰因为它们以字典形式操作行数据列名就是键。import csv # 读取CSV文件 with open(‘input.csv’, ‘r’, encoding‘utf-8-sig’) as f: # ‘utf-8-sig’ 处理带BOM的文件 reader csv.DictReader(f) for row in reader: # row 是一个 OrderedDict print(row[‘姓名’], row[‘邮箱’]) # 通过列名访问数据 # 写入CSV文件 headers [‘姓名’, ‘部门’, ‘工资’] rows [ {‘姓名’: ‘李四’, ‘部门’: ‘研发’, ‘工资’: ‘15000’}, {‘姓名’: ‘王五’, ‘部门’: ‘市场’, ‘工资’: ‘12000’}, ] with open(‘output.csv’, ‘w’, encoding‘utf-8-sig’, newline‘’) as f: writer csv.DictWriter(f, fieldnamesheaders) writer.writeheader() writer.writerows(rows)踩坑记录在Windows上写入CSV时务必指定newline‘’否则每行数据后面会多出一个空行。这是因为Windows和Unix的换行符处理方式不同csv模块需要自己来控制。3. 数据处理与转换核心代码数据处理是Python的强项无论是字符串清洗、日期处理还是集合运算都有简洁高效的写法。3.1 字符串处理与正则表达式字符串操作无处不在。除了常用的split(),strip(),join(),replace()正则表达式re模块是处理复杂文本模式的瑞士军刀。常用字符串模板# 1. 分割与合并 tags “python, java, c” tag_list [tag.strip() for tag in tags.split(‘,’)] # [‘python’, ‘java’, ‘c’] new_str ‘ | ‘.join(tag_list) # ‘python | java | c’ # 2. 格式化推荐 f-string Python 3.6 name, score “小明”, 95.5 msg f“学生{name}的分数是{score:.1f}分。” # 格式化浮点数保留一位小数 print(msg) # 3. 检查与填充 s “123abc” print(s.isdigit()) # False 检查是否全为数字 print(s.zfill(10)) # ‘0000123abc’ 左侧用0填充至指定宽度正则表达式实战片段正则表达式语法需要学习但几个经典模式足以应对大部分场景。import re text “我的电话是138-0013-8000 邮箱是 supportexample.com。” # 提取手机号简单模式 phone_pattern r‘\d{3}-\d{4}-\d{4}’ phones re.findall(phone_pattern, text) # [‘138-0013-8000’] # 提取邮箱地址 email_pattern r‘[a-zA-Z0-9._%-][a-zA-Z0-9.-]\.[a-zA-Z]{2,}’ emails re.findall(email_pattern, text) # [‘supportexample.com’] # 替换敏感信息 masked_text re.sub(r‘\d{3}-\d{4}’, ‘***-****’, text) # 将手机号中间四位打码 print(masked_text) # “我的电话是138-****-8000...”注意事项正则表达式虽然强大但复杂的模式可能难以维护且效率较低。对于结构化的文本如HTML、XML优先考虑使用专门的解析库如BeautifulSoup、lxml。3.2 日期时间处理告别手动计算datetime模块是处理日期时间的标准答案。第三方库dateutil和pandas.Timestamp在处理更复杂的场景时非常有用。基础日期操作from datetime import datetime, timedelta, date # 1. 获取当前时间 now datetime.now() print(f“当前时间: {now.strftime(‘%Y-%m-%d %H:%M:%S’)}”) # 格式化输出 # 2. 字符串与datetime互转最常用 date_str “2023-10-01” dt_obj datetime.strptime(date_str, “%Y-%m-%d”) # 字符串 - datetime new_str dt_obj.strftime(“%Y年%m月%d日”) # datetime - 字符串 # 3. 时间计算 today date.today() yesterday today - timedelta(days1) next_week today timedelta(weeks1) # 4. 计算日期差值计算年龄、工龄等 birthday date(1990, 5, 1) age_days (today - birthday).days age_years age_days // 365处理时区问题当你的应用涉及多时区用户时必须显式处理时区。pytz库是事实标准。from datetime import datetime import pytz # 创建一个带时区的时间 utc_now datetime.now(pytz.utc) # UTC时间 print(utc_now) # 时区转换 beijing_tz pytz.timezone(‘Asia/Shanghai’) beijing_time utc_now.astimezone(beijing_tz) print(beijing_time) # 本地时间关联时区常见坑点 naive_local datetime.now() # 这是一个“幼稚”时间没有时区信息 # 错误local_with_tz pytz.timezone(‘Asia/Shanghai’).localize(naive_local) # 可能引发歧义 # 正确做法始终先明确时间的意义是UTC还是某个具体时区的时间再进行转换。3.3 列表、字典与集合的高阶用法这些内置数据结构的方法用好了能写出非常“Pythonic”的代码。列表推导式与生成器表达式# 列表推导式快速生成新列表 numbers [1, 2, 3, 4, 5] squares [x ** 2 for x in numbers] # [1, 4, 9, 16, 25] even_squares [x ** 2 for x in numbers if x % 2 0] # 带条件过滤 # 生成器表达式节省内存用于迭代 large_gen (x * 2 for x in range(1000000)) # 不会立即创建100万个元素的列表 for value in large_gen: if value 100: break # 处理前几个值 # 字典推导式 names [‘Alice’, ‘Bob’, ‘Charlie’] name_length {name: len(name) for name in names} # {‘Alice’: 5, ‘Bob’: 3, ‘Charlie’: 7}字典的setdefault与defaultdict分组统计是常见任务这两种方式可以优雅地处理键不存在的情况。# 使用 setdefault 分组数据 data [‘apple’, ‘banana’, ‘apple’, ‘orange’, ‘banana’, ‘apple’] count_dict {} for fruit in data: count_dict.setdefault(fruit, 0) # 如果键不存在则设置为0 count_dict[fruit] 1 print(count_dict) # {‘apple’: 3, ‘banana’: 2, ‘orange’: 1} # 使用 collections.defaultdict 更简洁 from collections import defaultdict count_dict defaultdict(int) # 默认工厂函数是 int() 即0 for fruit in data: count_dict[fruit] 1 # 直接加无需判断键是否存在集合运算集合用于去重和数学集合运算效率极高。a {1, 2, 3, 4} b {3, 4, 5, 6} print(a | b) # 并集: {1, 2, 3, 4, 5, 6} print(a b) # 交集: {3, 4} print(a - b) # 差集 (在a中但不在b中): {1, 2} print(a ^ b) # 对称差集 (只在a或只在b中): {1, 2, 5, 6} # 列表去重最快方法 dup_list [1, 2, 2, 3, 3, 3] unique_list list(set(dup_list)) # 顺序可能丢失 # 如需保持顺序Python 3.7 字典键有序可利用此特性 from collections import OrderedDict unique_ordered list(OrderedDict.fromkeys(dup_list)) # [1, 2, 3]4. 函数、类与装饰器构建可复用代码块将常用逻辑封装成函数和类是代码复用的基础。装饰器则提供了强大的功能增强能力。4.1 函数编写的最佳实践一个设计良好的函数应该职责单一、参数清晰、有文档字符串。带类型提示和默认参数的函数模板from typing import List, Optional, Union def process_items( items: List[str], prefix: str “Item: “, max_items: Optional[int] None ) - List[str]: “““ 处理字符串列表添加前缀并限制返回数量。 参数: items: 待处理的字符串列表。 prefix: 要添加的前缀默认为“Item: “。 max_items: 最大返回数量为None则处理全部。 返回: 处理后的新列表。 “““ if max_items is not None: items items[:max_items] return [prefix item for item in items] # 使用 result process_items([“apple”, “banana”], max_items1) print(result) # [‘Item: apple’]提示类型提示Type Hints不会影响程序运行但能让IDE如VSCode、PyCharm提供更好的代码补全和错误检查也方便其他开发者理解你的代码。Optional[int]表示参数可以是int或None。使用*args和**kwargs处理可变参数def logger(func_name, *args, **kwargs): “““一个简单的日志函数记录函数调用参数。“““ args_str ‘, ‘.join(repr(arg) for arg in args) kwargs_str ‘, ‘.join(f‘{k}{repr(v)}’ for k, v in kwargs.items()) all_args ‘, ‘.join(filter(None, [args_str, kwargs_str])) print(f“[LOG] {func_name}({all_args})”) def connect_to_db(host, port5432, username, password): # 模拟数据库连接 logger(“connect_to_db”, host, port, usernameusername, password“***”) return f“Connected to {host}:{port}” connect_to_db(“localhost”, 5433, username“admin”, password“secret”) # 输出: [LOG] connect_to_db(‘localhost’, 5433, username‘admin’, password‘***’)4.2 类的__init__与常用魔术方法在__init__方法中初始化对象属性是最常见的操作。此外实现__str__和__repr__能让你自定义对象的字符串表示调试时非常有用。一个标准的类定义模板class Person: “““一个表示人的类。“““ def __init__(self, name: str, age: int): self.name name self.age age self._internal_id id(self) # 以单下划线开头暗示是“内部”属性 def __str__(self) - str: “““为用户提供的可读字符串表示。“““ return f“Person(name{self.name}, age{self.age})” def __repr__(self) - str: “““为开发者提供的精确字符串表示通常可用于重新创建对象。“““ return f“Person(‘{self.name}’, {self.age})” def greet(self) - str: return f“你好我是{self.name}今年{self.age}岁。” # 使用 p Person(“张三”, 30) print(p) # 调用 __str__: Person(name张三, age30) print(repr(p)) # 调用 __repr__: Person(‘张三’, 30) print(p.greet()) # 你好我是张三今年30岁。让对象支持比较和排序通过实现__eq__,__lt__等方法可以让自定义类的对象支持,,sorted()等操作。class Student: def __init__(self, name, score): self.name name self.score score def __eq__(self, other): if not isinstance(other, Student): return NotImplemented return self.score other.score def __lt__(self, other): if not isinstance(other, Student): return NotImplemented return self.score other.score # 定义了 __lt__ 后 sorted() 和 等操作会自动使用 def __repr__(self): return f“Student({self.name}, {self.score})” students [Student(‘李雷’, 88), Student(‘韩梅梅’, 95), Student(‘小明’, 88)] print(sorted(students)) # 按分数升序排序: [Student(小明, 88), Student(李雷, 88), Student(韩梅梅, 95)] print(Student(‘李雷’, 88) Student(‘小明’, 88)) # True 分数相同4.3 装饰器的编写与应用装饰器本质上是一个返回函数的高阶函数用于在不修改原函数代码的情况下增加功能。它理解起来有点绕但用起来非常强大。编写一个计时装饰器import time from functools import wraps # 使用 wraps 保留原函数的元信息 def timer(func): “““装饰器打印函数运行时间。“““ wraps(func) # 重要这能保留 func 的 __name__ 等属性 def wrapper(*args, **kwargs): start_time time.perf_counter() # 使用高精度计时器 result func(*args, **kwargs) end_time time.perf_counter() run_time end_time - start_time print(f“函数 {func.__name__} 运行耗时: {run_time:.4f} 秒”) return result return wrapper timer def slow_function(n): “““模拟一个耗时的函数。“““ time.sleep(n) return n slow_function(1) # 输出: 函数 slow_function 运行耗时: 1.0012 秒编写一个带参数的装饰器有时我们需要装饰器本身也能接收参数这就需要再嵌套一层函数。from functools import wraps def retry(max_attempts3, delay1): “““装饰器在函数执行失败时重试。“““ def decorator(func): wraps(func) def wrapper(*args, **kwargs): last_exception None for attempt in range(1, max_attempts 1): try: return func(*args, **kwargs) except Exception as e: last_exception e print(f“{func.__name__} 第{attempt}次尝试失败: {e}”) if attempt max_attempts: time.sleep(delay) print(f“{func.__name__} 重试{max_attempts}次后仍失败”) raise last_exception return wrapper return decorator retry(max_attempts2, delay0.5) def unstable_api_call(): # 模拟不稳定的API调用可能随机失败 import random if random.random() 0.7: raise ConnectionError(“API连接失败”) return “Success” # 运行此函数可能会看到重试日志核心理解装饰器retry(max_attempts2, delay0.5)的执行顺序是先调用retry(max_attempts2, delay0.5)它返回真正的装饰器函数decorator然后decorator再应用到unstable_api_call函数上。多一层包装是为了传递参数。5. 实用脚本与系统交互Python是编写自动化脚本的绝佳语言无论是操作文件系统、执行外部命令还是创建定时任务都非常方便。5.1 遍历目录与文件筛选os和pathlib模块Python 3.4 推荐是处理路径和文件系统的核心。使用pathlib进行现代路径操作from pathlib import Path import shutil # 1. 创建Path对象不会实际创建文件/目录 current_dir Path(‘.’).resolve() # 获取当前目录的绝对路径 target_file current_dir / ‘data’ / ‘report.txt’ # 使用 / 运算符拼接路径 # 2. 检查路径属性 print(target_file.exists()) # 是否存在 print(target_file.is_file()) # 是否是文件 print(target_file.parent) # 父目录 # 3. 遍历目录 log_dir Path(‘./logs’) if log_dir.exists() and log_dir.is_dir(): # 遍历所有 .log 文件 for log_file in log_dir.glob(‘*.log’): print(f“找到日志文件: {log_file}”) # 递归遍历所有子目录中的 .txt 文件 for txt_file in log_dir.rglob(‘*.txt’): print(f“递归找到文本文件: {txt_file}”) # 4. 创建目录如果不存在 output_dir Path(‘./output’) output_dir.mkdir(parentsTrue, exist_okTrue) # parentsTrue 可创建多级目录 # 5. 读写文件 content target_file.read_text(encoding‘utf-8’) # 读取文本 target_file.write_text(“新内容”, encoding‘utf-8’) # 写入文本根据扩展名、修改时间等筛选文件from pathlib import Path import time from datetime import datetime, timedelta def find_recent_files(directory, extension‘.py’, hours24): “““查找指定目录下最近N小时内修改过的特定扩展名的文件。“““ dir_path Path(directory) if not dir_path.is_dir(): return [] cutoff_time datetime.now() - timedelta(hourshours) recent_files [] for file_path in dir_path.rglob(f‘*{extension}’): if file_path.is_file(): # 获取文件的修改时间 mtime datetime.fromtimestamp(file_path.stat().st_mtime) if mtime cutoff_time: recent_files.append((file_path, mtime)) # 按修改时间倒序排序 recent_files.sort(keylambda x: x[1], reverseTrue) return [fp for fp, _ in recent_files] # 使用示例 files find_recent_files(‘./src’, ‘.py’, hours48) for f in files: print(f)5.2 执行系统命令与进程管理使用subprocess模块来安全地执行外部命令并获取其输出。安全地执行命令并获取输出import subprocess # 1. 执行命令并获取返回码和输出推荐 result subprocess.run( [‘ls’, ‘-lh’], # 命令以列表形式传入更安全 capture_outputTrue, # 捕获标准输出和错误 textTrue, # 以文本形式返回而非字节 cwd‘/tmp’ # 在指定目录下执行命令 ) print(“返回码:”, result.returncode) print(“标准输出:\n”, result.stdout) if result.stderr: print(“标准错误:\n”, result.stderr) # 2. 检查命令是否成功执行 try: completed subprocess.run( [‘git’, ‘status’], checkTrue, # 如果返回码非零则抛出 CalledProcessError 异常 capture_outputTrue, textTrue ) print(“Git状态正常”) except subprocess.CalledProcessError as e: print(f“命令执行失败返回码: {e.returncode}”) print(f“错误输出: {e.stderr}”) # 3. 执行管道命令例如统计当前目录下文件数量 ps subprocess.Popen([‘ls’, ‘-1’], stdoutsubprocess.PIPE) wc subprocess.Popen([‘wc’, ‘-l’], stdinps.stdout, stdoutsubprocess.PIPE) ps.stdout.close() # 允许 ps 接收 SIGPIPE 信号 output, _ wc.communicate() print(“文件数量:”, int(output.strip()))安全警告永远不要使用shellTrue并将未经清洗的用户输入拼接成命令字符串这会导致严重的命令注入安全漏洞。坚持使用列表形式传递命令和参数。5.3 定时任务与脚本调度对于简单的定时任务可以使用标准库的sched或threading.Timer。对于复杂的生产环境调度推荐使用APScheduler或操作系统级的cron(Linux) /计划任务(Windows)。使用threading.Timer实现简单定时import threading import time def print_every_5_seconds(): print(f“[{time.strftime(‘%H:%M:%S’)}] 定时任务执行”) # 再次设置定时器实现循环 threading.Timer(5, print_every_5_seconds).start() # 启动定时任务 print(“启动定时任务...”) print_every_5_seconds() # 主线程继续做其他事情 time.sleep(20) print(“主程序结束”) # 注意这是一个简单示例在实际长时间运行的程序中需要更优雅的停止机制。使用schedule库第三方需安装进行更人性化的任务调度import schedule import time def job(): print(“我每隔10秒运行一次”) def hourly_job(): print(“我每小时运行一次”) # 定义任务 schedule.every(10).seconds.do(job) schedule.every().hour.do(hourly_job) print(“调度器开始运行按 CtrlC 退出”) while True: schedule.run_pending() time.sleep(1) # 每秒检查一次避免CPU空转6. 网络请求与API调用模板requests库是Python中进行HTTP请求的事实标准其API设计简洁优雅。6.1 基础的GET与POST请求GET请求模板带错误处理和超时import requests from requests.exceptions import RequestException, Timeout def safe_get(url, paramsNone, timeout10): “““安全的GET请求包含基本的错误处理。“““ headers { ‘User-Agent’: ‘Mozilla/5.0 (My Python Script)’ } try: response requests.get( url, paramsparams, # 查询参数字典会自动编码 headersheaders, timeouttimeout # 连接和读取超时时间 ) # 检查HTTP状态码是否成功 response.raise_for_status() return response except Timeout: print(f“请求超时: {url}”) except RequestException as e: print(f“请求发生错误: {e}”) except Exception as e: print(f“未知错误: {e}”) return None # 使用 resp safe_get(“https://httpbin.org/get”, params{“key1”: “value1”, “key2”: “value2”}) if resp is not None: print(“状态码:”, resp.status_code) print(“响应头:”, resp.headers.get(‘Content-Type’)) # 根据内容类型解析响应 if ‘application/json’ in resp.headers.get(‘Content-Type’, ‘’): data resp.json() # 解析为JSON else: data resp.text # 解析为文本 print(data)POST请求模板提交表单或JSON数据import requests import json # 1. 提交表单数据 (application/x-www-form-urlencoded) form_data {‘username’: ‘testuser’, ‘password’: ‘testpass’} resp requests.post(‘https://httpbin.org/post’, dataform_data) print(resp.json()) # 2. 提交JSON数据 (application/json) json_data {‘title’: ‘测试文章’, ‘content’: ‘这是内容’, ‘tags’: [‘Python’, ‘API’]} resp requests.post( ‘https://httpbin.org/post’, jsonjson_data, # 使用 json 参数requests会自动序列化并设置Content-Type # 等价于: datajson.dumps(json_data), headers{‘Content-Type’: ‘application/json’} ) print(resp.json()) # 3. 上传文件 files {‘file’: (‘report.pdf’, open(‘report.pdf’, ‘rb’), ‘application/pdf’)} resp requests.post(‘https://httpbin.org/post’, filesfiles)6.2 处理会话、Cookie与重试对于需要登录或保持状态的网站需要使用Session对象。对于不稳定的网络可以配置重试机制。使用Session保持状态import requests # 创建一个会话所有通过该会话发出的请求会共享Cookie等信息 session requests.Session() # 1. 模拟登录假设登录接口返回设置Cookie login_data {‘user’: ‘admin’, ‘pass’: ‘secret’} login_resp session.post(‘https://example.com/login’, datalogin_data) login_resp.raise_for_status() # 2. 后续请求会自动携带登录后的Cookie profile_resp session.get(‘https://example.com/dashboard’) print(profile_resp.text) # 3. 可以为会话统一设置请求头 session.headers.update({‘Referer’: ‘https://example.com/’, ‘X-Custom-Header’: ‘MyValue’})为请求添加重试机制使用requests的适配器 (HTTPAdapter) 配合urllib3的Retry策略。import requests from requests.adapters import HTTPAdapter from urllib3.util.retry import Retry def create_session_with_retries( retries3, backoff_factor0.5, status_forcelist(500, 502, 504), sessionNone, ): “““创建一个配置了重试机制的会话。“““ session session or requests.Session() retry_strategy Retry( totalretries, readretries, connectretries, backoff_factorbackoff_factor, # 重试等待时间{backoff factor} * (2 ** (retry number - 1)) status_forceliststatus_forcelist, # 遇到这些状态码会强制重试 allowed_methods[“GET”, “POST”] # 只对GET和POST方法重试 ) adapter HTTPAdapter(max_retriesretry_strategy) session.mount(“http://”, adapter) session.mount(“https://”, adapter) return session # 使用 robust_session create_session_with_retries(retries2) try: resp robust_session.get(‘https://example.com/api’, timeout5) resp.raise_for_status() except requests.exceptions.RetryError as e: print(f“重试多次后仍然失败: {e}”)7. 常见问题排查与调试技巧即使有了完善的代码模板在实际运行中还是会遇到各种问题。掌握排查方法比记住答案更重要。7.1 异常捕获与日志记录不要使用裸露的except:这会捕获所有异常包括KeyboardInterrupt(CtrlC) 和SystemExit使得程序难以正常终止。精确的异常捕获模板import logging # 配置日志 logging.basicConfig( levellogging.INFO, format‘%(asctime)s - %(name)s - %(levelname)s - %(message)s’, handlers[ logging.FileHandler(‘app.log’, encoding‘utf-8’), logging.StreamHandler() ] ) logger logging.getLogger(__name__) def process_data(data_file): try: with open(data_file, ‘r’, encoding‘utf-8’) as f: content f.read() # 模拟一些处理 result int(content.strip()) * 2 logger.info(f“文件 {data_file} 处理成功结果: {result}”) return result except FileNotFoundError: logger.error(f“文件未找到: {data_file}”) # 可以选择返回一个默认值或重新抛出异常 return None except ValueError as e: logger.error(f“文件内容无法转换为数字: {data_file} 错误: {e}”) return None except Exception as e: # 捕获其他未预料到的异常并记录详细信息 logger.exception(f“处理文件 {data_file} 时发生未知错误”) # 这会记录完整的堆栈跟踪 raise # 重新抛出让上层调用者知道发生了严重错误 # 使用 process_data(‘valid_number.txt’) # 正常 process_data(‘non_existent.txt’) # 记录 FileNotFoundError process_data(‘invalid.txt’) # 文件内容为“abc”记录 ValueError使用traceback模块获取更详细的错误信息import traceback import sys def risky_operation(): return 1 / 0 try: risky_operation() except ZeroDivisionError: # 打印完整的异常堆栈信息到标准错误 traceback.print_exc() # 或者获取堆栈文本用于记录日志 error_msg traceback.format_exc() print(“捕获到错误详细信息已记录。”)7.2 性能分析与代码优化当程序变慢时需要找到瓶颈所在。cProfile和line_profiler是常用的性能分析工具。使用cProfile进行整体性能分析import cProfile import pstats from io import StringIO def slow_function(): total 0 for i in range(100000): for j in range(1000): total i * j return total def fast_function(): # 使用更高效的数学公式替代嵌套循环 (示例) n, m 100000, 1000 return sum(i * j for i in range(n) for j in range(m)) if __name__ ‘__main__’: # 方法1使用命令行 python -m cProfile your_script.py # 方法2在代码中嵌入 pr cProfile.Profile() pr.enable() # 开始性能分析 result slow_function() pr.disable() # 结束性能分析 print(f“结果: {result}”) # 将分析结果输出到流并排序 s StringIO() ps pstats.Stats(pr, streams).sort_stats(‘cumulative’) # 按累计时间排序 ps.print_stats(20) # 打印前20行 print(s.getvalue())定位具体代码行的耗时使用line_profiler第三方库首先安装pip install line_profiler。然后使用profile装饰器标记要分析的函数。# 假设此代码保存在 test_profile.py 中 # 运行方式: kernprof -l -v test_profile.py profile # 这是 line_profiler 的装饰器 def process_data_line_by_line(): data [i ** 2 for i in range(10000)] total 0 for num in data: # 这行可能被标记为耗时 if num % 2 0: # 这行可能被标记为耗时 total num return total if __name__ ‘__main__’: process_data_line_by_line()运行后line_profiler会输出每行代码的执行次数和耗时帮助你精准定位瓶颈。7.3 依赖管理与虚拟环境项目依赖混乱是另一个常见问题。务必使用虚拟环境隔离不同项目。使用venv创建虚拟环境Python 3.3 内置# 在项目根目录下 python -m venv venv # 创建名为 venv 的虚拟环境目录 # 激活虚拟环境 # Linux/macOS: source venv/bin/activate # Windows: venv\Scripts\activate # 激活后pip install 的包都会安装到该虚拟环境中 pip install requests pandas # 生成依赖列表 pip freeze requirements.txt # 退出虚拟环境 deactivate使用pip-tools管理精确的依赖版本pip freeze会包含所有间接依赖版本可能过于严格。pip-tools的pip-compile可以基于一个requirements.in文件只写你直接依赖的包生成一个精确的requirements.txt。# 安装 pip-tools pip install pip-tools # 创建 requirements.in写入直接依赖 # 文件内容示例: # requests2.25 # pandas2.0, 1.3 # 编译生成 requirements.txt pip-compile requirements.in # 根据 requirements.txt 安装所有依赖 pip-sync requirements.txt # 这会严格同步环境移除不在列表中的包我个人在实际使用中发现把这份“常用代码大全”当作一个活的笔记本来维护是最有效的。每当我在新项目中解决了一个具有通用性的问题或者学到了一种更优雅的写法我就会更新对应的代码片段并加上注释。久而久之它就成了我个人编码风格和最佳实践的沉淀也是带新人时最直接的参考资料。最后一个小建议是不要只收藏尝试把这些代码自己敲一遍并在实际的小项目中应用理解才会深刻才能真正变成你自己的东西。