程序员文章、书籍推荐和程序员创业信息与资源分享平台

网站首页 > 技术文章 正文

10 个改变我工作方式的 Python 习惯

hfteth 2025-07-23 14:10:39 技术文章 1 ℃

十年前,我的浏览器常年开着二十多个 StackOverflow 页面,只为搞清为什么又抛出“NoneType 不可迭代”的异常。如今,同事把问题抛给我,而我几乎不用搜索就能给出答案。区别不是天赋,而是下面这 10 个被我长期坚持的小习惯。它们没有一条是“用列表推导”这类老生常谈,却在日复一日的编码里悄悄重塑了我的效率。


1. 先放下 print,用 logging 把调试变成一分钟的事

还在用print()找 Bug 的人,往往在一堆输出里手动对齐时间戳。Python 自带的logging模块一次配置,终身受益:

import logging

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s | %(levelname)s | %(message)s'
)
logging.info("App started")

实践记录:我排查一个偶发的 API 超时问题时,只在关键路径加了两行logging.debug()。日志里精确到毫秒的时间差让我在一分钟内定位到是网络握手阶段卡死,而不是代码逻辑出错。


2. 为每个项目建独立虚拟环境,别给未来挖坑

命令只有一行,却常被忽略:

python -m venv .venv && source .venv/bin/activate

我统计过,近一年在 GitHub 上随机浏览的 90%公开项目都没有提交虚拟环境说明。结果可想而之:依赖版本冲突、代码在别人机器上跑不动。
.venv/写进.gitignore,你就已经在团队协作里领先一步。


3. 用 concurrent.futures 把慢任务并行,14 分钟缩短到几十秒

网络请求 IO 密集?CPU 运算密集?concurrent.futures两行代码给出答案:

from concurrent.futures import ThreadPoolExecutor

def fetch_url(url):
    # 网络请求或IO操作
    pass

urls = ["https://a.com", "https://b.com"]
with ThreadPoolExecutor() as executor:
    executor.map(fetch_url, urls)

如果是计算密集,把ThreadPoolExecutor换成ProcessPoolExecutor即可。
真实案例:我曾维护一个批量抓取并解析 500 个网页的脚本,串行跑需 15 分钟。引入线程池后,运行时间压到 50 秒,CPU 利用率从 10%提升到 85%。


4. dataclass 让类定义缩成三行,还附带 repr 和 eq

手写__init____repr____eq__的时代过去了:

from dataclasses import dataclass

@dataclass
class User:
    name: str
    age: int

对象打印出来就是清晰的User(name='Alice', age=30),无需额外代码。
需要更严格的类型校验时,直接叠加pydantic,迁移成本几乎为零。


5. 用 subprocess 写部署脚本,彻底告别易碎的 Bash

Bash 脚本在跨平台时往往因路径差异或引号问题崩掉。Python 的subprocess提供统一接口:

import subprocess

subprocess.run(['git', 'status'])

异常捕获、日志记录、条件分支都能用 Python 语法完成。
我所在团队曾用 30 行 Python 脚本替代 5 个互相关联的 Bash 部署脚本,上线后再也没有出现“在我机器上能跑”的尴尬。


6. 先跑 cProfile 再谈优化,别凭感觉改代码

性能瓶颈在哪?猜不准,就让数据说话:

import cProfile

cProfile.run('your_function()')

输出里自带每个函数的调用次数与耗时占比。我曾以为数据库查询拖慢了整个服务,跑完分析才发现 90%时间耗在一个正则表达式上。改一行代码,QPS 翻倍。


7. enumerate 和 zip 让循环易读又防错

for i, item in enumerate(my_list):
    print(i, item)

相比range(len(my_list)),既省去下标越界的隐患,又一眼看出意图。
同时遍历多个列表时,zip同样直观:

for name, age in zip(names, ages):
    ...

任何需要手动索引的场景,都值得先想想这两个内置函数能否直接解决。


8. 用生成器逐行吃文件,12GB 数据只占 100MB 内存

一次性把大文件读进内存,是最容易犯的内存错误:

def read_large_file(file_path):
    with open(file_path) as f:
        for line in f:
            yield line

for line in read_large_file('big.txt'):
    process(line)

生成器把文件变“流”,处理速度与内存占用解耦。
去年我解析 12GB 日志文件,全程内存峰值不到 100MB,机器没卡,咖啡也没凉。


9. argparse 把脚本包装成命令行工具,告别硬编码

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--file')
args = parser.parse_args()

print(args.file)

三步就能让脚本支持参数:

  1. 建解析器
  2. 加参数
  3. 解析

我把日常用的四个小脚本统一加上argparse,如今它们像系统命令一样常驻终端,随拿随用。


10. 用main守卫让模块既可导入也可直接运行

def main():
    print("Doing stuff")

if __name__ == "__main__":
    main()

这条习惯保证了代码既能被测试框架导入,也能在命令行直接执行。
任何 Python 文件都该以这个结构结尾,它让模块职责分明,日后拆分或打包都不会返工。


小结:不是技巧,而是默认动作

这 10 件事没有一条需要高智商,却需要把“知道”变成“肌肉记忆”:

  • 开新项目,先敲python -m venv .venv
  • 调试第一反应是加logging.debug而不是print
  • 写循环先想enumerate/zip
  • 提交前确认有if __name__ == "__main__"

坚持一年后,你会像我一样,从搜索答案的人变成被同事请教的人。

如果你正准备整理自己的 Python 工作流,不妨把这篇文章收藏,逐项对照,看看哪些习惯已经融入日常,哪些还需要刻意练习。真正的效率提升,不靠秘籍,靠把正确动作重复一千次。

Tags:

最近发表
标签列表