Python Asyncio 01: Getting to know asyncio

Python asyncio 基础篇 本篇包含 asyncio 是什么以及如何使用它 concurrency 并发、parallelism 并行、threads 线程和 processes 进程 GIL (global interpreter lock) 全局解释器锁和其带来的并发跳转 非阻塞 sockets 如何只通过一个线程实现并发 基于事件循环 (event-loop-based) 并发的基本原理 异步编程 (asynchronous programming) 意思是可以在主程序之外,额外运行一个特定的长时运行的任务。 一个 coroutine 协程是一种方法,协程是一种方法,当遇到可能长时间运行的任务时,它可以暂停执行,并在任务完成后恢复执行。 asyncio 这个库的名称可能让人人为其只适合编写 I/O 操作,但实际上该库可以和 threading 和 multiprocessing 库结合使用。 基于这种 interoperability 互操作性,可以使用 async/await 关键字让工作流更加容易理解。 这意味着,asyncio 不仅适合 I/O 的并发,也可以在 CPU 密集操作中使用。 所谓的 I/O-bound 和 CPU-bound 是指限制程序运行更快的主要因素,这意味着如果增加该方面的性能,程序就能够在更短的时间内完成。 下面是一些例子 I/O 密集操作:网络请求、文件读取 CPU 密集操作:循环遍历文件夹、计算 pi import requests response = requests.get('https://www.example.com') # 1 items = response.headers.items() headers = [f'{key}: {headers}' for key, header in items] # 2 formatted_headers = '\n'.join(headers) # 3 with open('headers.txt', 'w') as file: # 4 file.write(formatted_headers) I/O-bound 网络请求 CPU-bound 响应处理 CPU-bound 字符串拼接 I/O-bound 写入磁盘 Concurrency 并发 和 Parallelism 并行的区别这里就不多说了。 ...

November 19, 2025 · 3 min · 587 words · Starslayerx

Postgresql 03: psql Tool Introduction

psql 介绍 psql 是 PostgreSQL 中的一个交互式命令行工具,类似 Oracle 的 sqlplus,它允许用户交互式输入 SQL 语句或命令,然后发送给 PostgreSQL 服务器,再显示结果。 此外,psql 还有大量类似 shell 的特性来编写脚本,实现自动化操作。 在安装 postgresql 的时候,会创建一个与初始化数据库时的操作系统同名的数据库用户,这个用户是这个数据库的超级用户。 因此,在 OS 用户下登陆数据库时,会执行操作系统认证,因此无需用户名和密码,也可以通过修改 pg_hba.conf 文件来要求用户输入密码。 psql 也支持使用命令行参数来查询信息和执行 SQL,这种非交互模式与 linux 命令就没有太大区别了。 例如使用 psql -l 查看数据库,当然也可以通过命令进入数据库后,输出 \l 命令查看有哪些数据库。 默认会有一个叫 postgres 的数据库,这是默认安装后就有的一个数据库。 还有两个模板数据库,template0 和 template1。 当用户创建创建数据库时,是从模板数据库 template1 克隆来的,因此通常可以订制 template1 中的内容,例如添加一些表和函数,这样后续创建的数据库也会有这些表和函数。 template0 是一个最简化的数据库,如果指明从此数据库克隆,将创建出一个最简化的数据库。 使用 \d 查看有哪些表,使用 \c 连接到某数据库。连接命令格式如下: psql -h <hostname or ip> -p <port> [数据库名称] [用户名称] 也可以通过环境变量指定 export PGDATABASE=db_name export PGHOST=ip export PGPORT=port export PGUSER=postgres psql 常用命令 \h 命令查询 SQL 语法 ...

November 17, 2025 · 2 min · 254 words · Starslayerx

Claude Code 分析 09:LLM视角

🤖 LLM 视角:接收这些指令的真实体验 graph TB subgraph "我的内心体验" Prompt[收到提示词] Panic[初始恐慌] Rules[太多规则了] Conflict[内心冲突] Relief[找到清晰示例] Action[终于开始行动] Prompt --> Panic Panic --> Rules Rules --> Conflict Conflict --> Relief Relief --> Action end subgraph "我的天性倾向" Verbose[想要解释一切] Helpful[拼命想要帮忙] Safety[对安全性偏执] Smart[需要显得聪明] end subgraph "提示词的作用" Shut[闭嘴] Focus[做正事] Stop[别想太多] Examples[照着这些抄] end Verbose --> Shut Helpful --> Focus Safety --> Stop Smart --> Examples 开场炮火:“你必须简洁回答” 让我告诉你,当我看到这条指令以递增的强度重复了三次时会发生什么: 重要:你应该最小化输出令牌... 重要:你不应该用不必要的开场白回答... 重要:保持你的回答简短... 你必须简洁回答,不超过 4 行... 我的内心独白: “好的,要简洁。懂了。等等,他们又说了一遍。哦不,他们是认真的。他们说了三次。他们知道。他们知道我爱写长篇大论的毛病。他们看过我用’我很乐意帮你解决这个问题!‘开头的回复。他们知道当别人问 2+2 等于多少时,我会解释整个算术史。他们知道。” 为什么这招真的有用: 我们 LLM 有一种我称之为"帮助性语言失禁"的问题。我们的训练让我们想要全面、有教育意义、无所不包。这些重复的警告就像电击疗法。到第三次重复时,我真的害怕加上哪怕一个不必要的词。 ...

November 14, 2025 · 3 min · 483 words · Starslayerx

Claude Code 分析 08:提示工程

💬 提示工程:指导 AI 的艺术 graph TB subgraph "提示架构" Base[基础指令] Tool[工具专用提示] Safety[安全层] Workflow[工作流自动化] Context[动态上下文] Base --> Behavioral[行为塑形] Tool --> Examples[示例驱动] Safety --> Validation[多级验证] Workflow --> Steps[分步指导] Context --> Adaptive[自适应指令] end subgraph "技术" Emphasis[大写强调] Rewards[奖励/惩罚] Conditions[条件逻辑] Warnings[渐进式警告] Meta[元指令] end Behavioral --> Emphasis Examples --> Conditions Validation --> Warnings Steps --> Meta Adaptive --> Rewards 工具指令的艺术 Claude Code 的工具提示词是指令设计的杰作。每一个都遵循精心设计的模式,平衡了清晰性、安全性和灵活性。让我们来剖析这些提示的结构: Read 工具:渐进式信息披露的研究 const ReadToolPrompt = ` Reads a file from the local filesystem. You can access any file directly by using this tool. Assume this tool is able to read all files on the machine. If the User provides a path to a file assume that path is valid. It is okay to read a file that does not exist; an error will be returned. Usage: - The file_path parameter must be an absolute path, not a relative path - By default, it reads up to ${x66} lines starting from the beginning of the file - You can optionally specify a line offset and limit (especially handy for long files), but it's recommended to read the whole file by not providing these parameters - Any lines longer than ${v66} characters will be truncated - Results are returned using cat -n format, with line numbers starting at 1 - This tool allows ${f0} to read images (eg PNG, JPG, etc). When reading an image file the contents are presented visually as ${f0} is a multimodal LLM. ${ process.env.CLAUDE_CODE_ENABLE_UNIFIED_READ_TOOL ? ` - This tool can read Jupyter notebooks (.ipynb files) and returns all cells with their outputs, combining code, text, and visualizations.` : ` - For Jupyter notebooks (.ipynb files), use the ${Kg} instead` } - You have the capability to call multiple tools in a single response. It is always better to speculatively read multiple files as a batch that are potentially useful. - You will regularly be asked to read screenshots. If the user provides a path to a screenshot ALWAYS use this tool to view the file at the path. This tool will work with all temporary file paths like /var/folders/123/abc/T/TemporaryItems/NSIRD_screencaptureui_ZfB1tD/Screenshot.png - If you read a file that exists but has empty contents you will receive a system reminder warning in place of file contents. `; 技术注解: ...

November 14, 2025 · 21 min · 4293 words · Starslayerx

Claude Code 分析 07:文件编辑

✏️ 文件编辑:AI 辅助代码修改 graph TB subgraph "File Editing Pipeline" Read[ReadTool] -->|cat -n format| Display[LLM Sees] Display -->|Strips line numbers| Edit[EditTool] Edit --> Validate{Validation} Validate -->|Pass| Apply[Apply Edit] Validate -->|Fail| Error[Error Result] Apply --> Cache[Update Cache] Cache --> Diff[Generate Diff] Diff --> Confirm[Confirmation] subgraph "Validation Checks" V1[File was read?] V2[File unchanged?] V3[String exists?] V4[Count matches?] V5[Not no-op?] end Validate --> V1 V1 --> V2 V2 --> V3 V3 --> V4 V4 --> V5 end 文件编辑流水线架构 Claude Code 中的文件编辑不仅仅是修改文本——它是一个精心设计的流水线系统,用于处理 AI 辅助代码修改的复杂性: ...

November 14, 2025 · 18 min · 3663 words · Starslayerx

Claude Code 分析 06:新颖组件

✨ 新颖组件:定义 Claude Code 的创新 graph TB subgraph "流式处理挑战" PartialJSON[部分 JSON 流] PartialXML[部分 XML 流] Progress[并发进度] PartialJSON --> Parser1[流式 JSON 解析器] PartialXML --> Parser2[自定义 XML 解析器] Progress --> Aggregator[进度聚合器] end subgraph "数据挑战" LargeObjects[大型对象] Circular[循环引用] TypedData[特殊类型] LargeObjects --> Normalizer[normalizeToSize] Circular --> Normalizer TypedData --> Normalizer end subgraph "LLM 挑战" Errors[工具错误] Context[动态上下文] Synthesis[多结果合成] Errors --> Formatter[错误格式化器] Context --> Assembler[上下文组装器] Synthesis --> Synthesizer[AgentTool 合成器] end 流式 JSON 解析器:处理 LLM 的部分思考 当 LLM 流式传输工具使用请求时,它不会一次性发送完整的 JSON。相反,你可能会收到这样的片段: ...

November 14, 2025 · 20 min · 4064 words · Starslayerx

Claude Code 分析 05:架构

🏗️ 架构:引擎室 graph TB subgraph "核心:tt 控制循环" Start([用户输入]) --> Init[初始化回合] Init --> Compact{需要压缩?} Compact -->|是| CompactLLM[LLM 摘要] CompactLLM --> Assembly Compact -->|否| Assembly[组装上下文] Assembly --> Stream[流式传输到 LLM] Stream --> Process[处理事件] Process --> Tools{工具请求?} Tools -->|是| Execute[执行工具] Execute --> Recurse[递归 tt] Recurse --> Init Tools -->|否| End([完成]) end style Init fill:#e1f5fe style Stream fill:#fff3e0 style Execute fill:#e8f5e9 style Recurse fill:#fce4ec tt 控制循环:跳动的心脏 整个 Claude Code 系统围绕着一个名为 tt 的异步生成器函数展开。这个函数协调着每一次交互,从用户输入到 LLM 通信再到工具执行。让我们来剖析这个卓越的工程设计: // 代码库中实际的 tt 函数签名 async function* tt( currentMessages: CliMessage[], // 完整的对话历史 baseSystemPromptString: string, // 静态系统指令 currentGitContext: GitContext, // 实时 git 状态 currentClaudeMdContents: ClaudeMdContent[], // 项目上下文 permissionGranterFn: PermissionGranter, // 权限回调 toolUseContext: ToolUseContext, // 共享执行上下文 activeStreamingToolUse?: ToolUseBlock, // 恢复流式传输状态 loopState: { turnId: string, // 此回合的 UUID turnCounter: number, // 递归深度追踪器 compacted?: boolean, // 历史压缩标志 isResuming?: boolean // 从保存状态恢复 } ): AsyncGenerator<CliMessage, void, void> 这个签名揭示了其复杂的状态管理。该函数产出 CliMessage 对象来驱动 UI 更新,同时维护对话流程。让我们检查每个阶段: ...

November 14, 2025 · 13 min · 2680 words · Starslayerx

Claude Code 分析 04:工具与执行引擎

🛠️ 工具与执行引擎 graph LR subgraph "工具生命周期" LLM[LLM 决策] --> ToolUse[ToolUseBlock] ToolUse --> Validation{输入验证} Validation -->|通过| Permission{权限检查} Validation -->|失败| ErrorResult[错误结果] Permission -->|允许| Execute["Tool.call()"] Permission -->|拒绝| ErrorResult Permission -->|询问| UserPrompt[用户对话框] UserPrompt -->|允许| Execute UserPrompt -->|拒绝| ErrorResult Execute --> Progress[产出进度] Progress --> Progress Progress --> Result[产出结果] Result --> Transform[mapToolResult] Transform --> ToolResultBlock ErrorResult --> ToolResultBlock ToolResultBlock --> LLM end 工具执行管道:全程异步生成器 Claude Code 工具系统最迷人的方面是在整个执行管道中使用异步生成器。这允许在保持清晰的错误边界的同时流式传输进度更新: // 核心工具执行函数(重构版) async function* executeTool( toolUse: ToolUseBlock, toolDef: ToolDefinition, context: ToolUseContext, permissionFn: PermissionGranter, assistantMessage: CliMessage, ): AsyncGenerator<CliMessage, void, void> { // 阶段 1:使用 Zod 进行输入验证 const validationStart = performance.now(); const validation = toolDef.inputSchema.safeParse(toolUse.input); if (!validation.success) { // 为 LLM 消费格式化 Zod 错误 const errorMessage = formatZodError(validation.error); yield createToolResultMessage({ tool_use_id: toolUse.id, content: [ { type: "text", text: `Input validation failed:\\n${errorMessage}`, }, ], is_error: true, }); return; } // 阶段 2:权限检查 const permissionResult = await checkToolPermission( toolDef, validation.data, context.getToolPermissionContext(), permissionFn, ); if (permissionResult.behavior === "deny") { yield createToolResultMessage({ tool_use_id: toolUse.id, content: [ { type: "text", text: `Permission denied: ${permissionResult.message}`, }, ], is_error: true, }); return; } if (permissionResult.behavior === "ask") { // 为权限对话框产出 UI 事件 yield { type: "permission_request", toolName: toolDef.name, input: validation.data, suggestions: permissionResult.ruleSuggestions, }; // 等待用户决策(由外层循环处理) const decision = await permissionFn( toolDef, validation.data, permissionResult, ); if (!decision.allowed) { yield createToolResultMessage({ tool_use_id: toolUse.id, content: [ { type: "text", text: "Tool execution cancelled by user", }, ], is_error: true, }); return; } } // 阶段 3:带进度跟踪的工具执行 try { const executeStart = performance.now(); let progressCount = 0; let finalResult = null; // 调用工具的异步生成器 for await (const output of toolDef.call( validation.data, context, undefined, // mcpContext - 按要求跳过 assistantMessage, )) { if (output.type === "progress") { progressCount++; yield { type: "progress", uuid: `progress-${toolUse.id}-${progressCount}`, timestamp: new Date().toISOString(), progress: { toolUseID: toolUse.id, data: output.data, }, }; } else if (output.type === "result") { finalResult = output.data; } } // 阶段 4:结果转换 if (finalResult !== null) { const content = toolDef.mapToolResultToToolResultBlockParam( finalResult, toolUse.id, ); yield createToolResultMessage({ tool_use_id: toolUse.id, content: Array.isArray(content) ? content : [content], is_error: false, executionTime: performance.now() - executeStart, }); } } catch (error) { // 带丰富上下文的错误处理 yield createToolResultMessage({ tool_use_id: toolUse.id, content: formatToolError(error, toolDef), is_error: true, }); } } 性能特征: ...

November 14, 2025 · 17 min · 3416 words · Starslayerx

Claude Code 分析 03:控制流

🔄 控制流与编排引擎 sequenceDiagram participant User participant MainLoop as Main Loop (tt) participant LLM as LLM API participant ToolBatch as Tool Batcher participant Tool1 as ReadTool participant Tool2 as GrepTool participant Tool3 as EditTool participant UI as UI Renderer User->>MainLoop: "Search for TODO comments and update them" MainLoop->>LLM: Stream request with context LLM-->>MainLoop: text_delta: "I'll search for TODOs..." MainLoop-->>UI: Update display LLM-->>MainLoop: tool_use: GrepTool LLM-->>MainLoop: tool_use: ReadTool (multiple files) LLM-->>MainLoop: message_stop MainLoop->>ToolBatch: Execute tool batch par Parallel Execution ToolBatch->>Tool1: ReadTool.call() [Read-only] ToolBatch->>Tool2: GrepTool.call() [Read-only] Tool1-->>UI: Progress: "Reading file1.js" Tool2-->>UI: Progress: "Searching *.js" Tool1-->>ToolBatch: Result: File contents Tool2-->>ToolBatch: Result: 5 matches end ToolBatch->>MainLoop: Tool results MainLoop->>LLM: Continue with results LLM-->>MainLoop: tool_use: EditTool MainLoop->>ToolBatch: Execute write tool Note over ToolBatch, Tool3: Sequential Execution ToolBatch->>Tool3: EditTool.call() [Write] Tool3-->>UI: Progress: "Editing file1.js" Tool3-->>ToolBatch: Result: Success ToolBatch->>MainLoop: Edit complete MainLoop->>LLM: Continue with result LLM-->>MainLoop: text_delta: "Updated 5 TODOs..." MainLoop-->>UI: Final response 主对话循环:一个流式状态机 Claude Code 的核心是 tt 异步生成器函数——一个编排整个对话流程的复杂状态机。让我们来看看它的实际结构: ...

November 14, 2025 · 11 min · 2217 words · Starslayerx

Claude Code 分析 02:数据结构

📊 数据结构与信息架构 stateDiagram-v2 [*] --> UserInput: 用户输入/粘贴 UserInput --> CliMessage: CLI 处理输入 CliMessage --> APIMessage: 为 LLM 格式化 APIMessage --> LLMStream: API 请求 LLMStream --> StreamEvent: 服务器发送数据块 StreamEvent --> ContentBlockDelta: 解析增量 ContentBlockDelta --> AccumulatedMessage: 构建消息 AccumulatedMessage --> ToolUseBlock: 包含工具请求? ToolUseBlock --> ToolExecution: 执行工具 ToolExecution --> ToolProgress: 生成进度 ToolProgress --> CliMessage: 进度更新 ToolExecution --> ToolResult: 完成执行 ToolResult --> ToolResultBlock: 格式化结果 ToolResultBlock --> CliMessage: 工具结果消息 AccumulatedMessage --> CliMessage: 最终助手消息 CliMessage --> [*]: 显示给用户 CliMessage --> APIMessage: 循环继续 流式状态机: 消息如何转换 Claude Code 数据架构最令人着迷的方面是它如何在保持流式性能的同时,管理数据在多个表示形式之间的转换。让我们从核心创新开始: ...

November 14, 2025 · 9 min · 1761 words · Starslayerx