ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

别再重复造轮子了!Python这10个内置模块真能造!

别再重复造轮子了!Python这10个内置模块真能造! 项目里又看到一个 utils.py 两千多行。其内部存在手写路径拼接, 另有手写分组情况存在。同时还有手写重试部分, 亦有手写命令行参数解析这一操作。而且还有一个是自行封装的日志类。当初在看到这种文件的一瞬, 我便不太相信它。并且越是类似像那种所谓“万能工具箱”的样子, 便越有可能暗藏隐患让人踩坑。标准库里很多东西不是不能用是平时被忽略了。先瞧一瞧极为平常的活儿, 每日将一批订单 CSV 予以扫描, 把脏数据过滤掉, 依据用户把金额聚合起来, 最终输出异常日志。很多人会先造一堆函数其实用几个内置模块就够了。from pathlib import Path from collections import defaultdict from dataclasses import dataclass from datetime import datetime import csv import logging logging.basicConfig( filenamecheck_order.log, levellogging.INFO, format%(asctime)s %(levelname)s %(message)s ) dataclass classOrderLine: user_id: str order_id: str amount: int pay_time: datetime defload_orders(src_dir: str): root Path(src_dir) for file in root.glob(order_*.csv): with file.open(r, encodingutf-8, newline) as f: for row in csv.DictReader(f): try: yield OrderLine( user_idrow[user_id].strip, order_idrow[order_id].strip, amountint(row[amount]), pay_timedatetime.strptime(row[pay_time], %Y-%m-%d %H:%M:%S) ) except Exception as e: logging.info(bad row file%s row%s err%s, file.name, row, e) money_by_user defaultdict(int) for item in load_orders(./data): money_by_user[item.user_id] item.amount for user_id, total in money_by_user.items: if total 100000: logging.info(large user user_id%s total%s, user_id, total)这里面已经用了 6 个模块。路径的处理方式, 不要再采用./data/ 这样拼接了 , Linux 的路径分隔符是不一样的 , 早晚会被环境弄得很糟心一次。CSV读取表格, 相较于自行使用split()而言更为可靠, 当字段中含有逗号、引号以及换行符时, 依靠手写进行解析基本上宛如埋下隐患。适合放置这类临时业务对象出来并非所有物品都得往上放 , 也并非所有对象都需手写而成。并非仅仅是获取当下的时间, 在较多的情形之中, 会将字符串转化为切实能够进行比较、能够开展计算的时间。. 用来分组、计数、聚合比到处写if key notin result: result[key] 0 result[key] value清爽太多。更别提了, 线上脚本最怕仅仅只会print, 运行结束后什么都没留存下来, 特别是定时任务, 失败一回没人发觉, 到了第二天数据就对不上了。再说几个我平时用得很顺手的。适配于处置批量性质的数据, 举例说, 类似接口一回具备最多查二百个订单这样子的状况, 切莫自已来编排一堆下标判定。from itertools import islice defchunked(items, size): it iter(items) while batch : list(islice(it, size)): yield batch order_ids [A1001, A1002, A1003, A1004] for batch in chunked(order_ids, 2): print(call remote api:, batch)这个代码短但比很多“分页工具类”稳。我一般拿来做两件事缓存和保留函数上下文。比如某个配置文件一天读不了几次但代码里到处要用from functools import lru_cache import json from pathlib import Path lru_cache(maxsize1) defget_rule_config: text Path(./rule.json).read_text(encodingutf-8) return json.loads(text) defcheck_channel(channel): rules get_rule_config return channel in rules.get(enabled_channels, [])此处在稍加便利之处运用了json编码, 莫轻易小瞧它, 其于接口落盘环节发挥作用, 于配置读取阶段助力不少, 于排除故障之时会对响应进行格式化处理, 几乎每日都会与之遭遇一遍。是很多脚本最该用、但最容易被偷懒跳过的模块。import argparse parser argparse.ArgumentParser parser.add_argument(--day, requiredTrue, help账单日期例如 2026-06-01) parser.add_argument(--dry-run, actionstore_true) args parser.parse_args print(args.day, args.dry_run)有了它, 脚本并非只能通过修改源码才能够运行了。这种差别是比较大的, 特别是在将其交给运维人员之后, 或者是放置到流水线当中进行执行的时候。最后一个 。不要随意去胡调 shell, 要是到了得跟系统命令配合的情况, 千万别再用 os.乱弄。import subprocess ret subprocess.run( [grep, -c, TimeoutError, app.log], textTrue, capture_outputTrue ) if ret.returncode 0: print(timeout count:, ret.stdout.strip) else: print(grep failed:, ret.stderr)os, 仅仅能够获取一个退出码, 对于标准输出以及错误输出进行处理都存在难题。在排障脚本当中, 这种情况令人甚是恼怒。这 10 个模块我再拎一下你的内容似乎不完整且比较混乱, 不太明确具体要如何改写, 如果以上输出并不符合需求, 请提供更准确清晰的句子以便我进行改写。它们不花哨也不新。很多项目当中存在着“公共工具类”, 将其拆开来看, 实际上就是又一次去编写了前面提及的那些模块, 并且编写的情况还比不上标准库那般具备清晰明了的边界状况。现在, 我在看脚本, 第一眼并非看使用了何种高级库, 而是看是不是存在乱造轮子的情况。其路径运用手拼方式, 日志借助print达成所需效果而获取体现展现, 参数选取修改源码渠道来予以确定, 分组依据一堆若指定键不在字典之中的if语句来加以实现。这种代码能跑。但一上定时任务、一接真实数据、一换机器毛病就开始出来了。
返回列表