7个Python库,快速搞定公司内部工具
那天我正准备下班,领导从我后面飘过来一句:“东哥,搞个小工具,自动导一下各部门的日报,不难,就你顺手的事。”听到这句话我脑袋里条件反射三个字:又 来 了。 但说实话,公司内部那点破事儿,用 Python 真的是手到,不能说擒来吧,起码是勉强能擒。
我现在干这种内部小工具,基本就围着 7 个库转圈,换业务、换同事、换老板都没关系,库不怎么换。之前我写性能压测选 Postgres 不选 MySQL 那篇你们可能看过,里面各种压测脚本我也是拿这套东西糊的。
先说命令行工具这块哈。你公司内部要搞那种“运维双击 bat、开发敲命令”的小脚本,第一个一定是 typer。argparse 也能用,就是长得太丑,写起来还费事。typer 用起来有点像装了语法糖版的 click。比如领导要的“导日报”:
# daily_report.py
import typer
from pathlib import Pathapp = typer.Typer()
@app.command()
defexport(dept: str = typer.Argument(..., help="部门,比如 dev、qa"),
date: str = typer.Option(None, "--date", "-d", help="日期,默认今天")):
ifnot date:
from datetime import date as _d
date = _d.today().isoformat()
out = Path(f"report_{dept}_{date}.xlsx")
# 这里调用真正的导出逻辑,先打印代替
typer.echo(f"[INFO] 正在导出 {dept}{date} 的日报 -> {out}")
# TODO: generate_report(dept, date, out)
if __name__ == "__main__":
app()
你看,写完以后给测试同学说一句:python daily_report.py export dev -d 2025-01-01,他自己就会玩了,不用再问“参数是空格分隔还是等号分隔”。这种省沟通成本的东西,能救命的。
第二个,基本跟 typer 绑在一起用的,就是 rich。你知道吧,程序能跑和跑得“像样”,这是两回事。内部工具也是,控制台全是纯黑白日志,谁爱用?随便加个进度条,大家立刻觉得你这个工具专业度上来了半个台阶。
from time import sleep
from rich.progress import trackdefsync_users():
users = ["张三", "李四", "王五", "产品经理"]
for u in track(users, description="同步用户中..."):
# 假装在调别的系统
sleep(0.3)
# do_sync(u)
有一次我半夜在预发环境排查 SpringBoot 默认配置害我线程池爆掉的问题,顺手给自己写了个巡检脚本,用 rich 把异常服务高亮出来,凌晨两点看着那个彩色控制台,整个人竟然还有点小成就感……
然后肯定绕不开第三个:requests。公司内部只要有两个系统能对上话,最后基本都得变成“互相调 HTTP 接口”。你写工具不跟它打交道是不可能的。比如搞一个从 OA 拉请假记录的小脚本:
import requestsBASE_URL = "http://oa.internal/api"
defget_leaves(dept: str):
url = f"{BASE_URL}/leave/list"
try:
resp = requests.get(url, params={"dept": dept}, timeout=5)
resp.raise_for_status()
except requests.RequestException as e:
# 真实场景最好打日志,不要只 print
print(f"[ERROR] 调 OA 失败:{e}")
return []
data = resp.json()
# 假设统一用 code 字段判断
if data.get("code") != 0:
print(f"[WARN] OA 返回异常:{data}")
return []
return data.get("data", [])
注意我这里强行加了 timeout 和 raise_for_status(),就是不想再重演一次“Feign 默认超时太短,上游早就放弃了,下游还在傻乎乎干活”的血案。 内部工具也一样,别轻易相信对方接口永远稳。
讲完“和别人说话”,就轮到“自己玩 Excel”了。公司内部 80% 的小工具,最后都会变成一句话:帮我把这些 CSV/数据库数据,整成一个漂亮的 Excel 给我。这时候第四个、第五个一起上:pandas + openpyxl。
pandas 负责脏活累活,把一堆七零八落的数据洗干净;openpyxl 负责最后那点“体面”,比如加个筛选、合并个单元格之类。
import pandas as pddefgenerate_report(dept: str, date: str, out_file: str):
# 假装从数据库查出来
rows = [
{"name": "小明", "hours": 8, "dept": dept},
{"name": "小红", "hours": 6, "dept": dept},
]
df = pd.DataFrame(rows)
# 简单汇总一下
summary = df["hours"].sum()
df.loc[len(df)] = ["合计", summary, dept]
with pd.ExcelWriter(out_file, engine="openpyxl") as writer:
df.to_excel(writer, index=False, sheet_name="日报")
你别小看这几十行,很多时候你给老板的是一个“每周自动发到他邮箱的 Excel”,他根本不关心后面是 Postgres、MySQL 还是你手写 JSON 文件,他只会觉得:“哦,这个同学还挺懂业务的。”
再往上一个段位,就是给大家一个网页点点就完事,不想让他们装 Python、配环境、记命令。这时候第六个库登场:FastAPI(Flask 也行,我最近比较常用 FastAPI)。
我之前给生产同事弄过一个“小小系统”:上传一个设备导出的 log,点个按钮,它会自动帮你解析、拆包、算偏移,然后告诉你是不是中了那个 1024 字节的坑。 前期我自己本地用脚本跑,后面发现大家都要用,就随手套了个 FastAPI 壳子:
from fastapi import FastAPI, UploadFile, File
from fastapi.responses import JSONResponseapp = FastAPI()
@app.post("/check-log")
asyncdefcheck_log(file: UploadFile = File(...)):
raw = await file.read()
ok = b"0x1234abcd"in raw # 伪逻辑,别当真
return JSONResponse({
"ok": ok,
"msg": "报文结构正常"if ok else"疑似长度字段错位,建议抓包复查"
})
然后再配个简单的前端页面,测试、运维、现场支持都能自己玩,谁也不用远程连你电脑。“一人写,万人用”这种工具,做多了你就会对 FastAPI 产生感情。
最后一个,第七个库,属于给懒人准备的:APScheduler。你总不能天天晚上九点准点坐在电脑前,敲命令导数据、发邮件吧,做人要有点自动化精神。
from apscheduler.schedulers.blocking import BlockingScheduler
from datetime import datetimedefjob():
print(f"[{datetime.now()}] 开始跑日报任务……")
# 这里可以调用前面那个 generate_report
# generate_report(...)
if __name__ == "__main__":
scheduler = BlockingScheduler()
# 每天 20:30 跑一次
scheduler.add_job(job, "cron", hour=20, minute=30)
scheduler.start()
有一次测试环境 Kafka 消费积压,他们喊我排查“消息是不是丢了”,我顺手写了个小工具半小时扫一遍 offset 差值,顺嘴又挂上 APScheduler 定时跑,把结果塞进企业微信机器人里发群里——从那天起,每天晚上机器人都会自动在群里碎碎念一次,现在谁要还说“感觉有消息丢了”,我就甩群里那张图给他看。
你看啊,这 7 个库串起来,大概就覆盖了公司内部 90% 的“啊你帮我搞个小工具吧”这种需求:
想给自己用: typer+rich,舒服一点;想跟别的系统打交道: requests;想给老板报表: pandas+openpyxl;想给全公司用: FastAPI搞个小 Web;不想天天手点: APScheduler定时跑。
剩下那 10% 的离谱需求,比如“东哥你能不能写个脚本,把我们所有系统的默认配置自动优化一下”,这种我一般都是先叹口气,喝口水,再考虑要不要装作网断了。