Python技术迷

好家伙,妥妥的 Python Master

别一上来就想写解释器、造框架。对绝大多数人来说,“Python Master”大概是这些能力的综合:

  • 业务来了,脑子里自然会冒出几个 Python 解决方案,还能评估哪个最合适
  • 看别人一坨代码,不至于一脸懵,能快速找到问题点,手起刀落重构
  • 碰到性能瓶颈、线上异常,不会只会加日志瞎猜,知道怎么定位、怎么验证
  • 有自己的代码习惯和工程套路,不是到处 copy 粘贴

你看,其实跟我以前写数据库、MQ那堆排查经历是一个路子:把细节吃透,踩过足够多坑,自然就“像那么回事”了

下面我就按“从能写,到写好,再到玩明白”的节奏来聊聊。

基础要会到什么程度,才算像样?

很多人学 Python 的路线是:刷语法题、做选择题……说实话,这种方式只够你写“能跑的脚本”,离“Master”差得远。

我觉得基础阶段,至少要做到:

  • 基本语法写起来不需要查:列表、字典、集合、切片、函数、类
  • 理解“值”和“引用”的区别,别天天被可变类型坑
  • 会用虚拟环境、依赖管理,知道 pip/venv/poetry 是干嘛的
  • 能看懂别人稍微正经一点的项目结构,不迷路

随便给一段“基础里带点进阶味”的小例子,你可以对照自己现在的写法看看差在哪:

from pathlib import Path
from contextlib import contextmanager
from typing import Iterator, List


@contextmanager
defopen_log(path: Path) -> Iterator[Iterator[str]]:
"""一个简单的上下文管理器包一层,顺便加点日志。"""
    print(f"[INFO] Reading log from {path}")
    f = path.open("r", encoding="utf-8")
try:
yield f
finally:
        print("[INFO] Done")
        f.close()


deffind_error_lines(path: str) -> List[str]:
    log_path = Path(path)
ifnot log_path.exists():
raise FileNotFoundError(f"log file not found: {path}")

    errors: List[str] = []
with open_log(log_path) as f:
for idx, line in enumerate(f, start=1):
if"ERROR"in line:
                errors.append(f"#{idx}: {line.rstrip()}")
return errors


if __name__ == "__main__":
for line in find_error_lines("app.log"):
        print(line)

这里面其实就揉进去了不少“以后你肯定会用到”的东西:

  • pathlib.Path 代替裸字符串
  • contextmanager 自己封装小工具
  • typing 提前养成写类型标注的习惯
  • enumerate 这种常见的 Pythonic 写法

你要是读起来挺顺、还能自己改造,那基础差不多就够用可以往上走了。

别只刷题,多写点真有用的小东西

我身边所有写 Python 写得不错的人,几乎都有一堆“杂七杂八的小脚本”:批处理 Excel、日志分析、接口巡检、小爬虫、自动化部署脚本…… 这些东西有两个好处:

  1. 立刻能解决你工作里的真问题,反馈快
  2. 会逼着你接触到文件操作、网络请求、异常处理、定时任务这些“真实世界”的细节

比如,你可以搞一个“接口健康巡检”的小脚本,挂到 crontab 上,每隔几分钟跑一下:

import time
from typing import Dict
import requests


URLS: Dict[str, str] = {
"user": "https://api.example.com/user/health",
"order": "https://api.example.com/order/health",
}


defcheck_services(timeout: float = 2.0) -> Dict[str, bool]:
    result: Dict[str, bool] = {}
for name, url in URLS.items():
try:
            resp = requests.get(url, timeout=timeout)
            result[name] = resp.status_code == 200
except requests.RequestException:
            result[name] = False
return result


defmain() -> None:
    statuses = check_services()
    now = time.strftime("%Y-%m-%d %H:%M:%S")
for name, ok in statuses.items():
        status_text = "OK"if ok else"DOWN"
        print(f"[{now}] {name}: {status_text}")


if __name__ == "__main__":
    main()

这个东西很简单,但里面几乎涵盖了一大堆常见能力:

  • 网络请求、超时时间、异常捕获
  • 命令行脚本入口
  • 打印结构化一点的日志

你多写几类这种脚本,其实思路就慢慢往“工程化”方向靠了——这跟我以前排查 Feign 超时、各种网络问题时的思维方式是一致的

从“写得能跑”到“写得优雅”:进阶语法要上场了

等你不再紧张“语法会不会写错”的时候,就可以稍微“讲究”一点了。Python 的强大,很多时候就是体现在这种小语法糖和抽象能力上。

几个一定要熟练用的东西:

  • 列表推导式 / 字典推导式
  • 生成器(yield)、惰性计算
  • with 上下文管理
  • 装饰器(简单场景先会用,后面再研究原理)

来看一个处理大文件的例子,假设你需要从一个巨大的日志文件里统计某接口的平均耗时,如果全读到内存里肯定爆:

from pathlib import Path
from typing import Iterable, Iterator


defread_lines(path: Path) -> Iterator[str]:
with path.open("r", encoding="utf-8") as f:
for line in f:
yield line.rstrip("\n")


deffilter_api_log(lines: Iterable[str], api_name: str) -> Iterator[str]:
for line in lines:
if api_name in line:
yield line


defparse_cost(lines: Iterable[str]) -> Iterator[float]:
for line in lines:
# 假设日志里有这样的片段 cost=123.45ms
if"cost="notin line:
continue
try:
            part = line.split("cost=")[1].split("ms")[0]
yield float(part)
except (IndexError, ValueError):
continue


defavg_cost(path: str, api_name: str) -> float:
    log_path = Path(path)
    lines = read_lines(log_path)
    api_lines = filter_api_log(lines, api_name)
    costs = list(parse_cost(api_lines))
return sum(costs) / len(costs) if costs else0.0


if __name__ == "__main__":
    print(avg_cost("app.log", "/api/order/create"))

这里的套路你体会一下:

  • 每个函数都做一件很小的事
  • 通过生成器一环套一环,内存占用可控
  • 逻辑线性、清晰,测试也很方便

你以后做 ETL、日志分析、数据清洗,这一套都能复用。

工程化:项目结构、日志、测试一个都别躲

“写脚本”和“写项目”的区别,最大的其实在于:你要开始为未来的自己(和同事)负责了。

最简单的一个项目结构,可以从这样开始:

my_project/
  my_project/
    __init__.py
    config.py
    models.py
    services/
      __init__.py
      user_service.py
      order_service.py
  tests/
    test_user_service.py
  pyproject.toml / requirements.txt
  main.py

然后,最起码要有像样的日志,而不是乱 print。比如:

import logging
from logging.handlers import RotatingFileHandler
from pathlib import Path


defsetup_logger() -> logging.Logger:
    log_dir = Path("logs")
    log_dir.mkdir(exist_ok=True)

    logger = logging.getLogger("app")
    logger.setLevel(logging.INFO)

    handler = RotatingFileHandler(
        log_dir / "app.log",
        maxBytes=5 * 1024 * 1024,
        backupCount=3,
        encoding="utf-8"
    )
    formatter = logging.Formatter(
"%(asctime)s [%(levelname)s] %(name)s - %(message)s"
    )
    handler.setFormatter(formatter)
    logger.addHandler(handler)

# 控制台也打一份
    console = logging.StreamHandler()
    console.setFormatter(formatter)
    logger.addHandler(console)

return logger


logger = setup_logger()


defcreate_user(username: str) -> None:
    logger.info("creating user: %s", username)
# TODO: 你的业务逻辑
# 如果抛异常,日志会带堆栈
    logger.info("user created: %s", username)


if __name__ == "__main__":
    create_user("alice")

再往上,一个合格的 Python 项目一定要有测试。哪怕先从最简单的 pytest 开始:

# tests/test_math_utils.py
from my_project.math_utils import add


deftest_add():
assert add(1, 2) == 3

你会发现,当你开始写测试之后,代码结构会被迫变得更清晰,这一点在我排查各种主从同步、网络奇怪 bug 的时候体现得特别明显:可测的代码,问题定位永远更快

学会跟 Bug 和 性能问题“谈判”

想走到“Master”这个段位,debug 和性能分析一定是绕不过去的。

  1. 日志 + 断点调试
  • logging 用好,日志级别分清楚(DEBUG/INFO/WARNING/ERROR)
  • 用 pdb 或者 IDE 自带的断点,别全靠 print

举个极简的 pdb 用法:

import pdb


deftricky_calc(x: int, y: int) -> int:
    pdb.set_trace()  # 程序跑到这里会停下来
return x // y


if __name__ == "__main__":
    tricky_calc(10, 0)

跑的时候你可以一步步看变量、执行路径,比瞎猜强太多。

  1. 性能优化一点点来

不要一上来就想着用 C 扩展、写 Rust;多数时候,你只要:

  • 换个数据结构(列表 -> 集合、字典)
  • 把重复计算的逻辑抽出去缓存
  • 用生成器减少内存峰值
  • 合理地用多进程/多线程/协程

就够用了。

例如简单测试某段代码的耗时:

from time import perf_counter


defslow_func():
return sum(i * i for i in range(10_000_000))


if __name__ == "__main__":
    t0 = perf_counter()
    slow_func()
    t1 = perf_counter()
    print(f"cost: {t1 - t0:.3f}s")

你可以写个小装饰器,把这种耗时统计封装掉,挂到关键路径上看一下。

并发和异步:别急着全都学,但要知道有什么

Python 的并发有点绕,但对“Master”来说,至少要搞清楚三个东西各自适合啥场景:

  • threading:IO 密集型任务可以用,多数 Web 框架背后都会用到
  • multiprocessing:CPU 密集型,比如大规模计算
  • asyncio:大量 IO 并发,比如高并发爬虫、网关、IM 服务之类

给你丢一段很简单的 asyncio 风格代码,感受一下写法:

import asyncio
from typing import List

import aiohttp


asyncdeffetch(session: aiohttp.ClientSession, url: str) -> int:
asyncwith session.get(url, timeout=2) as resp:
await resp.text()
return resp.status


asyncdefmain(urls: List[str]) -> None:
asyncwith aiohttp.ClientSession() as session:
        tasks = [fetch(session, u) for u in urls]
for coro in asyncio.as_completed(tasks):
            status = await coro
            print("got status:", status)


if __name__ == "__main__":
    urls = [
"https://httpbin.org/get",
"https://example.com",
"https://python.org",
    ]
    asyncio.run(main(urls))

真到你要做这种活的时候,再系统地补一遍协程、事件循环的知识,其实效率会更高。

想往“Master”靠拢,有几个习惯特别关键:

  1. 多看高质量源码

  • 标准库:pathlib、logging、functools、itertools
  • 常用三方:FastAPI、Requests、Pydantic 这种
  • 写点自己的轮子,但别乱造比如自己做个简单的配置管理、小型 ORM、轻量任务调度器,主要是练设计能力

  • 记录踩坑过程我很多对底层的理解,其实都是从一次次“奇葩 bug 排查记录”里冒出来的

  • 到这个阶段,你回头看自己第一年写的 Python,多少都会想删库跑路——那大概率说明你真的在进步。

    -END-

    我为大家打造了一份RPA教程,完全免费:songshuhezi.com/rpa.html

    🔥虎哥私藏精品🔥

    虎哥作为一名老码农,整理了全网最全《python高级架构师资料合集》,总量高达650GB