每个进程出生时自带三条"管子": stdin (标准输入, fd=0) ← 进程从这里读数据 (键盘/管道) stdout (标准输出, fd=1) → 进程把正常结果写到这里 stderr (标准错误, fd=2) → 进程把错误信息写到这里 日常类比: stdin = 你的耳朵 (听输入) stdout = 你的嘴巴 (说正常话) stderr = 你的紧急电话 (报错误) 在 Claude Code hooks.rs:162-165 中: child.stdin(
()
| 89 | # ============================================================ |
| 90 | |
| 91 | def lesson_2_standard_streams(): |
| 92 | """ |
| 93 | 每个进程出生时自带三条"管子": |
| 94 | |
| 95 | stdin (标准输入, fd=0) ← 进程从这里读数据 (键盘/管道) |
| 96 | stdout (标准输出, fd=1) → 进程把正常结果写到这里 |
| 97 | stderr (标准错误, fd=2) → 进程把错误信息写到这里 |
| 98 | |
| 99 | 日常类比: |
| 100 | stdin = 你的耳朵 (听输入) |
| 101 | stdout = 你的嘴巴 (说正常话) |
| 102 | stderr = 你的紧急电话 (报错误) |
| 103 | |
| 104 | 在 Claude Code hooks.rs:162-165 中: |
| 105 | child.stdin(Stdio::piped()); // 把 stdin 连到管道 (我们写数据进去) |
| 106 | child.stdout(Stdio::piped()); // 把 stdout 连到管道 (我们读数据出来) |
| 107 | child.stderr(Stdio::piped()); // 把 stderr 也连到管道 |
| 108 | """ |
| 109 | print("=" * 60) |
| 110 | print("第二课: stdin / stdout / stderr — 进程的三个嘴巴") |
| 111 | print("=" * 60) |
| 112 | |
| 113 | # ---- 例 1: 捕获 stdout 和 stderr ---- |
| 114 | print() |
| 115 | print(" 例 1: 分别捕获 stdout 和 stderr") |
| 116 | print(" ────────────────────────────────") |
| 117 | |
| 118 | # 这个命令: 先往 stdout 写正常输出, 再往 stderr 写错误 |
| 119 | result = subprocess.run( |
| 120 | ["python3", "-c", textwrap.dedent("""\ |
| 121 | import sys |
| 122 | print("正常输出: 文件已读取") # → stdout |
| 123 | print("警告: 文件较大", file=sys.stderr) # → stderr |
| 124 | """)], |
| 125 | capture_output=True, |
| 126 | text=True, |
| 127 | ) |
| 128 | print(f" stdout: {result.stdout.strip()}") |
| 129 | print(f" stderr: {result.stderr.strip()}") |
| 130 | print(f" 退出码: {result.returncode}") |
| 131 | |
| 132 | # ---- 例 2: 通过 stdin 传数据给子进程 ---- |
| 133 | print() |
| 134 | print(" 例 2: 通过 stdin 传数据 (Hook 的核心机制!)") |
| 135 | print(" ─────────────────────────────────────────") |
| 136 | |
| 137 | # Claude Code hooks.rs:174 做的事: |
| 138 | # child.output_with_stdin(payload.as_bytes()) |
| 139 | # 即: 通过 stdin 把 JSON payload 传给 hook 脚本 |
| 140 | |
| 141 | hook_script = textwrap.dedent("""\ |
| 142 | import sys, json |
| 143 | # 从 stdin 读取 JSON |
| 144 | data = json.load(sys.stdin) |
| 145 | tool = data['tool_name'] |
| 146 | event = data['hook_event_name'] |
| 147 | print(f"Hook 收到: {event} -> {tool}") |
| 148 | """) |
no test coverage detected