
1. 从“t3code”这个名字说起它到底是什么第一次看到“t3code”这个词很多人会下意识地把它当成某个开源库的包名或者某个内部项目的代号。我最初也是这么想的直到我在几个技术社区里反复看到有人拿它当话题才意识到它更像是一个轻量级的代码片段管理与快速执行工具链的代称——注意这里说的是“代称”因为“t3code”本身并不是一个官方注册的产品名而是圈子里对一类“Tier-3 Code”实践的简称指的是那些不追求大而全、只解决具体小问题、随手就能跑起来的三行代码级方案。说白了t3code 的核心思路就是用最少的代码行数完成一个明确的小任务。它可能是一个把 CSV 转成 JSON 的脚本可能是一个批量重命名文件的命令组合也可能是一个定时抓取某个页面标题的小工具。它不追求工程化不追求可维护性甚至不追求优雅它追求的是当下就能跑、跑完就丢、下次要用再写一遍也不心疼。这个思路听起来有点“反工程”但实际用下来你会发现它解决了一个非常真实的痛点大部分日常小任务根本不值得你打开 IDE、建项目、配环境、写测试、提交仓库。你只是想快速验证一个想法或者临时处理一批数据这时候 t3code 式的做法反而效率最高。适合看这篇内容的人我大致分三类第一类是刚入行的开发者还在被“工程化思维”压得喘不过气想找一种更轻的做事方式第二类是有一定经验但日常被杂事缠身的老手需要一套快速处理琐事的套路第三类是非技术岗但需要偶尔写点脚本的人比如运营、产品、数据分析师你们不需要懂架构只需要能跑通。接下来我会从设计思路、核心细节、实操过程、常见问题四个大块把 t3code 这套玩法拆开讲清楚。每一块都会配上我实际踩过的坑和验证过的参数你可以直接抄作业。2. t3code 的整体设计思路与选型逻辑2.1 为什么是“三行”而不是“三十行”“t3code”里的“t3”我倾向于理解为Tier-3也就是第三层级的代码。第一层级是生产级代码有完整的测试、文档、CI/CD第二层级是项目级代码有模块划分、依赖管理、版本控制第三层级就是片段级代码它只存在于你的终端历史、临时文件或者聊天记录里。为什么要把代码限制在“三行”左右因为一旦超过三行你就开始需要上下文了。你需要记住变量名、需要知道上一行干了什么、需要处理异常。而三行以内的代码基本可以做到看一眼就懂、复制就能跑、跑完不用记。我实测下来三行是一个很微妙的阈值。比如用 Python 处理一个 JSON 文件import json data json.load(open(input.json)) print([item[name] for item in data[items]])三行搞定。如果你要加异常处理、加参数解析、加输出格式化那就奔着十行去了这时候你就该考虑是不是该写个正经脚本了。注意三行不是硬性规定而是一个心理锚点。它的真正含义是“不要为了一个小任务引入不必要的抽象”。2.2 工具选型为什么我最终留在了 Python Shell在 t3code 这个场景下工具选型只有一个标准启动速度。你不可能为了处理一个临时任务去等 JVM 启动也不可能去配一个 Node 环境再装一堆依赖。我试过用 Node、Ruby、Go 来写这类片段最后发现最顺手的组合是Python 做数据处理 Shell 做文件操作和流程编排。Python 的优势在于标准库足够厚json、csv、re、os、sys、subprocess这些模块基本覆盖了日常小任务的需求不需要额外装包。Shell 的优势在于它天生就是干“把几个命令串起来”这件事的而且终端里随手就能敲。至于为什么不用 Go 或 Rust原因很简单编译需要时间。哪怕只编译几秒钟也破坏了“随手就能跑”的体验。而 Python 和 Shell 是解释执行的写完回车就出结果。2.3 代码存放策略不建仓库但要有“回收站”t3code 的另一个核心设计是不建正式仓库。你不需要为每个片段创建一个 Git 项目那样反而增加了管理成本。我的做法是维护一个~/t3code/目录里面按日期或主题放.py和.sh文件文件名就是一句话描述比如20250115_csv_to_json.py。这个目录不需要提交到远程但我会定期用tar打包备份到移动硬盘。这样既保留了“随手写”的轻量感又避免了“写完就丢、下次重写”的浪费。提示如果你用 VS Code可以把这个目录加到工作区用CtrlP快速搜索文件名。实测比翻终端历史快得多。3. 核心细节解析与实操要点3.1 输入输出的约定让每个片段都能独立运行t3code 片段最重要的设计原则是自包含。也就是说每个片段都应该能独立运行不依赖外部配置文件、不依赖环境变量、不依赖其他片段的输出。输入要么是命令行参数要么是标准输入要么是固定路径的文件输出要么是标准输出要么是固定路径的文件。这样做的好处是你可以在任何时间、任何目录下运行它不用担心“上次那个环境还在不在”。我见过太多人写的小脚本过两周自己都跑不起来就是因为依赖了一个当时临时设的环境变量。具体做法上我习惯用argparse处理参数用sys.stdin处理管道输入。比如一个统计文本行数的小工具import sys lines sys.stdin.read().splitlines() print(f总行数: {len(lines)}, 非空行数: {len([l for l in lines if l.strip()])})这样你可以cat file.txt | python count_lines.py也可以python count_lines.py file.txt两种方式都能跑。3.2 错误处理只处理“会打断流程”的错误生产级代码要求你处理所有可能的异常但 t3code 片段不需要。你只需要处理那些会导致脚本直接崩溃、让你拿不到结果的错误。比如文件不存在、JSON 解析失败、网络请求超时。我的做法是在关键步骤外面包一层try/except捕获后打印一条人能看懂的错误信息然后sys.exit(1)。不要写复杂的重试逻辑不要写日志轮转那些都是第二层级以上才需要考虑的事。import json, sys try: data json.load(open(sys.argv[1])) except FileNotFoundError: print(f文件不存在: {sys.argv[1]}); sys.exit(1) except json.JSONDecodeError as e: print(fJSON 格式错误: {e}); sys.exit(1)三行核心逻辑加上三行错误处理总共六行依然在可接受范围内。3.3 参数传递位置参数优先可选参数用默认值在 t3code 场景下我强烈建议优先使用位置参数而不是--key value这种形式。因为位置参数敲起来快而且不需要记参数名。比如python rename.py old_prefix new_prefix比python rename.py --old old_prefix --new new_prefix少敲十几个字符。只有在参数可选、且有合理默认值的时候才用argparse的可选参数。比如输出格式默认是 JSON但你可以用--format csv覆盖。注意不要用input()做交互式输入。t3code 片段的定位是“管道里的一环”交互式输入会破坏可组合性。3.4 依赖管理能用标准库就不用第三方库这是 t3code 的铁律。一旦你pip install了一个包这个片段就失去了“随手就能跑”的能力因为换一台机器就得重新装。我统计过自己过去半年写的 40 多个片段只有 3 个用了第三方库分别是requests发 HTTP 请求、beautifulsoup4解析 HTML和pandas处理 Excel。对于这三个例外我的做法是在片段开头用注释写明依赖并且尽量把依赖控制在“一个包”以内。比如# 依赖: pip install requests import requests r requests.get(https://example.com/api) print(r.json()[status])这样即使换机器看到注释就知道要装什么不会抓瞎。4. 实操过程与核心环节实现4.1 环境准备五分钟搭好你的 t3code 工作台你不需要装任何新东西只要系统里有 Python 3 和 Bash 就行。我建议做三件事第一创建目录mkdir -p ~/t3code cd ~/t3code。第二在.bashrc或.zshrc里加一个别名alias t3cd ~/t3code这样在任何地方敲t3就能跳过去。第三创建一个模板文件template.py内容如下#!/usr/bin/env python3 # 用途: # 依赖: 无 import sys, json, os, re def main(): # 你的三行核心逻辑 pass if __name__ __main__: main()以后每次写新片段就cp template.py 20250115_xxx.py然后改三行核心逻辑。实测这个习惯能帮你省下大量“从零开始写 import”的时间。4.2 第一个实战片段批量重命名文件假设你下载了一堆图片文件名是IMG_001.jpg到IMG_100.jpg你想改成photo_001.jpg这种格式。用 Shell 一行就能搞定for f in IMG_*.jpg; do mv $f photo_${f#IMG_}; done拆解一下${f#IMG_}是 Shell 的参数扩展意思是“去掉变量 f 开头匹配 IMG_ 的部分”。所以IMG_001.jpg就变成了001.jpg再加上photo_前缀最终就是photo_001.jpg。这个片段我用了不下五十次每次处理不同前缀的文件只需要改IMG_和photo_两个地方。注意一定要先ls IMG_*.jpg确认匹配范围再执行mv否则改错了很难批量改回来。4.3 第二个实战片段CSV 转 JSON 并筛选字段假设你有一个users.csv包含id,name,email,age四列你只想导出name和email两列成 JSON。用 Python 标准库csv和json就能搞定import csv, json, sys with open(sys.argv[1]) as f: rows list(csv.DictReader(f)) result [{name: r[name], email: r[email]} for r in rows] print(json.dumps(result, ensure_asciiFalse, indent2))运行python csv_to_json.py users.csv output.json就得到了干净的 JSON 数组。这里ensure_asciiFalse是为了让中文正常显示indent2是为了方便人眼阅读。如果你要传给程序处理可以把indent去掉体积能小三分之一。提示csv.DictReader默认用第一行做表头如果你的 CSV 没有表头需要传fieldnames参数。4.4 第三个实战片段定时抓取页面标题这个稍微复杂一点需要requests和beautifulsoup4。但代码依然控制在十行以内# 依赖: pip install requests beautifulsoup4 import requests, sys from bs4 import BeautifulSoup r requests.get(sys.argv[1], timeout10) soup BeautifulSoup(r.text, html.parser) print(soup.title.string.strip() if soup.title else 无标题)配合crontab就能定时抓取。比如每天早上八点抓一次0 8 * * * /usr/bin/python3 ~/t3code/fetch_title.py https://example.com ~/t3code/titles.log这里timeout10很重要不加的话遇到慢站点会一直卡住。是追加写入不会覆盖历史记录。4.5 参数计算与选择过程以超时时间为例上面那个抓取片段里timeout10是我实测下来的经验值。我试过 5 秒发现有些站点在高峰期确实需要 8 到 9 秒才能返回试过 30 秒结果遇到死链时等了半分钟才报错体验很差。10 秒是一个平衡点大部分正常站点能在 3 秒内返回10 秒足够覆盖慢速情况又不会让你等太久。如果你抓的是内网服务可以降到 3 秒如果抓的是海外站点可以升到 15 秒。这个参数没有标准答案取决于你的具体场景。5. 常见问题与排查技巧实录5.1 编码问题中文乱码的三种解法这是 t3code 片段里最常见的问题。你从 CSV 读中文输出到终端变成乱码或者你写文件时用了默认编码在 Windows 上打开就乱码。我的排查顺序是第一确认源文件编码。用file -i input.csv看是utf-8还是gbk。如果是gbk读取时加encodinggbk。第二确认输出编码。Python 3 的open()默认用系统编码在 Windows 上可能是gbk在 Linux 上通常是utf-8。我习惯显式写encodingutf-8。第三确认终端编码。用echo $LANG看是不是en_US.UTF-8或zh_CN.UTF-8。如果不是export LANGzh_CN.UTF-8再试。下面这张表是我整理的常见编码问题速查现象可能原因解决方法读取 CSV 报 UnicodeDecodeError文件是 GBK 编码open(..., encodinggbk)输出 JSON 中文变成 \uXXXX没加 ensure_asciiFalsejson.dumps(..., ensure_asciiFalse)终端显示问号终端编码不是 UTF-8export LANGzh_CN.UTF-8写入文件后 Windows 打开乱码写入时用了 UTF-8 无 BOM用encodingutf-8-sig5.2 路径问题相对路径和绝对路径的坑t3code 片段经常在“当前目录”和“脚本所在目录”之间搞混。比如你写了一个脚本放在~/t3code/但在~/Downloads/下运行脚本里写open(data.csv)就会找不到文件因为它找的是~/Downloads/data.csv。我的做法是输入文件用命令行参数传绝对路径输出文件用当前目录的相对路径。这样你既知道输入在哪也知道输出会落在哪。如果你确实需要脚本自己找同目录的文件用os.path.dirname(os.path.abspath(__file__))获取脚本所在目录import os base os.path.dirname(os.path.abspath(__file__)) config_path os.path.join(base, config.json)5.3 权限问题Permission denied 的排查在 Linux 和 macOS 上你写了一个.sh文件直接./script.sh会报Permission denied。这是因为文件没有执行权限。解决方法是chmod x script.sh。但更常见的情况是你用sudo运行了一个脚本结果生成的文件属主变成了root下次用普通用户运行就写不进去了。我的建议是尽量不要用 sudo 跑 t3code 片段除非确实需要访问系统目录。如果已经产生了 root 属主的文件用sudo chown $USER:$USER filename改回来。5.4 管道断裂BrokenPipeError 的处理当你把 Python 脚本的输出通过管道传给head时head读够行数就退出了Python 这边还在往管道里写就会报BrokenPipeError。这个错误不影响结果但会在终端里刷一堆红字很难看。解决方法是在脚本开头加import signal signal.signal(signal.SIGPIPE, signal.SIG_DFL)这样管道断裂时 Python 会安静退出不会打印错误。这个技巧我在写tail -f类似的流式处理片段时经常用。5.5 常见问题速查表问题排查命令解决方向脚本找不到which python3确认 Python 路径模块找不到python3 -c import xxx装依赖或换标准库文件找不到ls -la 路径检查路径和权限输出为空echo $?看退出码0 表示成功但可能没输出执行太慢time python3 script.py定位耗时步骤内存爆了free -h改用流式处理不要一次读入提示echo $?是排查脚本问题的第一命令它告诉你上一个命令的退出码。0 是成功非 0 是失败。养成习惯能省很多时间。6. 我踩过的坑和独家避坑技巧6.1 不要用 t3code 处理生产数据这是我用血泪换来的教训。有一次我用一个三行脚本批量修改了生产环境的配置文件结果因为没做备份改错了一个字符导致服务重启后起不来。后来我给自己定了一条规矩t3code 片段只能用于本地临时文件、测试数据和只读操作。任何涉及生产环境、涉及写操作、涉及不可逆变更的任务都必须走正式流程。如果你确实需要用脚本处理重要数据至少做两件事第一先cp一份备份第二先用echo代替实际命令跑一遍确认输出符合预期再真正执行。6.2 给每个片段加一行注释说明用途我早期写的片段文件名是script1.py、script2.py过了一个月完全想不起来是干什么的。后来我强制自己每个片段开头写一行# 用途: xxx文件名也改成描述性的比如20250115_merge_two_csv.py。这个习惯看起来很小但实际节省的时间非常可观。6.3 定期清理但不要删太快~/t3code/目录会越积越多我一般每季度清理一次。但我的做法是先移到~/t3code/archive/过一个月再删。因为经常出现这种情况刚删掉一个片段第二天就遇到类似需求。移到 archive 目录既保持了工作目录的清爽又留了后悔药。6.4 用set -e让 Shell 片段更安全写 Shell 片段时默认情况下某一行出错脚本会继续往下执行这可能导致更严重的错误。在脚本开头加set -e可以让任何一行返回非零退出码时立即停止。配合set -u未定义变量报错和set -o pipefail管道中任一环节出错就报错三个一起写set -euo pipefail这三行我每个 Shell 片段都会加实测能避免 80% 的“莫名其妙跑歪了”的问题。6.5 不要过度追求“一行流”网上有很多“一行 Python 搞定 XXX”的炫技帖但我在实际使用中发现一行流往往可读性极差改一个参数都要想半天。t3code 追求的是“三行左右”而不是“一行”。多出来的两行用来做变量赋值和错误处理反而让片段更容易复用和修改。比如这个一行流print(sum(1 for l in open(f.txt) if l.strip()))改成三行lines open(f.txt).readlines() non_empty [l for l in lines if l.strip()] print(len(non_empty))虽然后者多两行但你想改成“统计包含关键词的行数”时只需要改中间一行前者就要重新理解整个表达式。长期来看三行流更划算。7. 这套玩法还能怎么扩展t3code 的思路不仅适用于写代码还可以扩展到其他场景。比如你在做数据分析时可以把常用的数据清洗步骤拆成一个个三行片段用 Jupyter Notebook 的单元格来组织你在做运维时可以把常用的排查命令写成三行以内的 Shell 函数放在.bashrc里随时调用。我最近还在尝试把 t3code 的思路用到文档处理上用pandoc加三行参数把 Markdown 转成 PDF用ffmpeg加三行参数批量压缩视频。核心逻辑是一样的找到最小可用的命令组合跑完就丢下次要用再拼一遍。如果你也想开始这套玩法我的建议是从今天开始把你重复做了三次以上的小任务写成三行片段存到~/t3code/。一个月后回头看你会发现自己的效率提升不是来自某个大工具而是来自这些不起眼的小片段。