跳到主要内容

命令行程序边界

命令行程序通过参数、环境变量、标准流、文件和退出状态与外界交互。请将每一项都视为公共接口,因为其他程序可能会依赖这些行为。

标准流

  • stdin:输入数据。
  • stdout:预期的结果输出。
  • stderr:诊断信息和进度提示,不应干扰管道处理。

input()stdin 读取一行;只有提供提示参数时才会先打印提示符。它适用于交互式工具,但不适合数据管道。处理流式输入时,直接遍历 sys.stdin;面向用户的输出使用 print,运行时的操作日志使用 logging

import sys

for line in sys.stdin:
sys.stdout.write(line.upper())

如果输出需要被机器解析,请保持纯净,不要混入标题、颜色代码或临时日志。当脚本需要消费结果时,提供独立的 JSON 等结构化模式。

参数与配置

使用 argparse 而非手动解析 sys.argv

import argparse
from pathlib import Path

parser = argparse.ArgumentParser()
parser.add_argument("input", type=Path)
parser.add_argument("--format", choices=("text", "json"), default="text")
args = parser.parse_args()

参数是显式的,会出现在进程列表和 Shell 历史中,因此不适合传递敏感信息。环境变量适合传递继承的部署配置,但它们本质上是字符串,可能通过进程检查或诊断日志泄露,并非安全的密钥存储。

import os

endpoint = os.environ.get("APP_ENDPOINT", "https://example.invalid")

在程序启动阶段一次性解析并验证配置。如果业务逻辑依赖此区别,需区分“变量未设置”和“变量值为空”。严禁在库代码深处修改进程级环境变量。

退出状态

成功返回 0,失败返回有文档记录的非零状态。使用 main 函数可以让这一契约变得可测试:

def main() -> int:
...
return 0

if __name__ == "__main__":
raise SystemExit(main())

异常是内部控制流机制;退出状态和 stderr 才是对外的 CLI 契约。仅在边界处捕获异常,将其转化为有用的诊断信息和稳定的退出码。保留足够的调试上下文,但避免打印敏感信息或完整的敏感载荷。

参考

探索关联

这篇笔记还没有文档关联。

同主题的其他笔记 (47)

打开关联网络