
8 个能立刻用上的 Python 开发效率技巧——从 python -m 告别导入报错,到 rich 让调试输出一目了然,再到 dataclasses 省掉一半样板代码。每个技巧都附带可直接复制的代码示例。
先看一个对比。这是大多数 Python 初学者写的代码:
import os# 手动拼路径,丑且容易出错data_dir = os.path.join("project", "data", "2024", "raw")config_file = os.path.join(data_dir, "config.json")# 手动计数器i = 0items = ["requests", "httpx", "aiohttp"]for item in items:print(f"{i}: {item}") i += 1# 手写 __init__,纯体力活class APIConfig:def __init__(self, url, timeout, retries):self.url = urlself.timeout = timeoutself.retries = retriesdef __repr__(self):return f"APIConfig(url={self.url}, timeout={self.timeout}, retries={self.retries})"这是改完之后的:
from pathlib import Pathdata_dir = Path("project") / "data" / "2024" / "raw"config_file = data_dir / "config.json"items = ["requests", "httpx", "aiohttp"]for i, item in enumerate(items):print(f"{i}: {item}")from dataclasses import dataclass@dataclassclass APIConfig: url: str timeout: int retries: int少了快一半代码,可读性反而更高。下面逐个拆解这些技巧。
我写了 4 年多 Python,发现一个规律:真正拖慢开发速度的,不是你不会某个算法,而是一堆"小不爽"在消耗你。
比如:
ImportError,查了半天发现是路径写法不对__init__,像在做填空题os.path 拼路径,代码看着像正则表达式这些不是大问题。但当它们每天出现 20 次,一周就是 140 次微小摩擦。
下面这 8 个技巧,每一个解决一类"小不爽"。不需要学新框架,不需要重构整个项目——今天看了明天就能用。
本文所有示例基于 Python 3.9+,大部分特性 3.7+ 就支持。唯一需要额外安装的库是 rich:
pip install rich其余都是 Python 标准库自带,不用装任何东西。
python -m 运行脚本,告别导入报错新手习惯这样跑脚本:
python app/main.py项目一大,迟早会撞上这个报错:
ImportError: attempted relative import with no known parent package换一种方式:
python -m app.mainPython 会把你的代码当作正经模块来执行,导入路径自动对齐项目根目录。越是多人协作、多层目录的项目,这个习惯越值钱。
我见过一个实习生因为这个报错 debug 了两个小时,最后改了一行命令就好了。
rich 让调试输出像 IDE 一样清晰标准 print() 够用,但丑。当你调试嵌套字典或复杂 JSON 时,满屏黑白文字很难一眼定位问题。
from rich import printdata = {"user": "小王","requests": 142,"errors": [ {"code": 503, "msg": "Service Unavailable", "count": 12}, {"code": 429, "msg": "Rate Limited", "count": 7}, ],}print(data)输出自动带上语法高亮和格式化缩进,嵌套结构一目了然。
再加一行:
from rich.traceback import installinstall()之后所有异常的回溯信息都会变成彩色分层的格式。这看起来像"锦上添花",实际上可读的调试信息直接降低认知负荷——而认知负荷正是隐藏的生产力杀手。
pathlib 替代 os.path老项目中到处都是这种写法:
import osconfig_path = os.path.join("project", "config", "app.yaml")if os.path.exists(config_path): content = open(config_path).read()pathlib 是 Python 3.4 就有的标准库,但很多人一直没用起来:
from pathlib import Pathconfig_path = Path("project") / "config" / "app.yaml"if config_path.exists(): content = config_path.read_text()用 / 拼路径比 os.path.join() 直观太多。而且 Path 对象自带 read_text()、write_text()、read_bytes()、glob() 等方法,不用再调 open() 了。
# 遍历目录下所有 CSV 文件for csv_file in Path("data").glob("*.csv"):print(csv_file.read_text())你一旦用习惯,再回去看 os.path 会觉得像在用 Java 写文件操作。
dataclasses 消灭样板代码如果你的类主要就是存数据,手写 __init__ 纯属体力劳动:
from dataclasses import dataclass@dataclassclass LLMConfig: model: str = "claude-sonnet-4-6" temperature: float = 0.7 max_tokens: int = 4096三行搞定。自动获得 __init__、__repr__、__eq__。
这在 API 开发、配置管理、ETL 管道里特别实用——省掉的不只是打字,更是心智开销。你一眼就能看清这个类有哪些字段、什么类型、默认值是多少。
enumerate() 和列表推导式还在这样写?
i = 0for name in names:print(i, name) i += 1Python 标准库十年前就替你解决了:
for i, name in enumerate(names):print(i, name)同理,把 4 行映射写成 1 行:
# 之前results = []for n in numbers: results.append(n * 2)# 之后results = [n * 2 for n in numbers]但记住一句话:如果你的推导式看起来像被熬夜巫师写出来的数学证明,换回普通 for 循环。六个月后的你会感谢现在的你。
if __name__ == "__main__" 保护入口这不是"高级技巧",但大量 Python 开发者跳过它:
def main():# 你的脚本逻辑 process_data() generate_report()if __name__ == "__main__": main()为什么重要?因为早晚有一天你会:
没有这个守卫,import 时脚本可能意外执行——触发 API 调用、写数据库、发邮件。凌晨两点被报警叫醒,通常就是因为这种"小疏忽"。
别问我怎么知道的。
---:用 time.perf_counter() 做性能测试
很多人测代码性能顺手写:
import timestart = time.time()# ... 你的代码 ...print(time.time() - start)time.time() 是看钟用的,不适合 benchmark。它精度不够,而且受系统时间调整的影响。
正确做法:
from time import perf_counterstart = perf_counter()# ... 你的代码 ...elapsed = perf_counter() - startprint(f"耗时: {elapsed:.4f} 秒")perf_counter() 专为性能测量设计,精度更高、不受系统时间跳变影响。你在优化 API 响应、数据处理管道时,这 0.001 秒的精度差别会非常关键——尤其是当那段代码在生产环境跑了 40 万次。
watchdog 实现热重载"改一行代码 → 切到终端 → 重新运行 → 看结果 → 再改一行"这个循环,每天至少重复几十次。
pip install watchdog然后:
watchmedo auto-restart --patterns="*.py" -- python your_script.py保存文件后脚本自动重启。尤其在调试 API 调用或数据处理流程时,这个体验像开挂一样。
等你习惯了这个节奏,手动重跑脚本会感觉像在用 2006 年的翻盖手机。
这 8 个技巧都不难,但有几点要注意:
python -m 的路径写法:用点分隔而非斜杠。app/main.py → app.main,写错了会报 No module named。dataclasses 的可变默认值陷阱:不要在字段默认值里直接用 [] 或 {},用 field(default_factory=list)。if 条件时,果断换普通循环。同事会感谢你的。perf_counter() 的返回值:单位是秒,但起点不保证是某个固定时间点——只用来算差值。把以上技巧串起来的日常开发模板:
"""日常 Python 脚本模板 —— 每个新项目从这里开始"""from pathlib import Pathfrom time import perf_counterfrom dataclasses import dataclassfrom rich import printfrom rich.traceback import installinstall() # 全局美化异常回溯@dataclassclass Config: data_dir: str = "data" output_dir: str = "output"def process_files(config: Config) -> list[Path]:"""读取 data_dir 下所有 CSV,返回文件路径列表""" data_path = Path(config.data_dir)if not data_path.exists():raise FileNotFoundError(f"目录不存在: {config.data_dir}")return list(data_path.glob("*.csv"))def main(): start = perf_counter() config = Config() files = process_files(config)for i, f in enumerate(files):print(f"[{i}] {f.name}")print(f"\n[green]处理完成,共 {len(files)} 个文件,耗时 {perf_counter() - start:.3f}s[/green]")if __name__ == "__main__": main()把这个模板保存下来,下次新建 Python 脚本时直接复制,省掉环境初始化的"冷启动"时间。
下一步可以玩什么?
rich 的进度条(rich.progress)接入你的数据处理循环watchdog 监听文件目录,自动触发数据处理流程dataclasses 换成 pydantic.BaseModel,给配置类加上自动校验这些技巧本身很小。但每天少踩的坑、少写的样板代码、少耗的认知资源,一个月下来就是质变。
真正的效率不是"敲键盘更快"——是把精力留给值得思考的问题。
