Python asyncio 03: A first asyncio application

Working with blocking sockets socket 是在网络中读取和写入数据的一种方式。 可以将 socket 看成一个邮件,将信封放到里面后运送到接收者的地址。 下面使用 Python 的内置 socket 模块来创建一个简单的 server import socket server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 这里,给 socket 函数指定了两个参数,第一个是 socket.AF_INET,这个告诉我们要与什么类型的地址进行交互,在这个例子中是 hostname 和 phonenumber。 第二个是 socket.SO_REUSEADDR,这个参数是说我们使用 TCP 协议进行交互。 然后使用 socket.setsockopt 方法将 socket.SOL_SOCKET 标志设置为 1。这将允许在关闭和快速重启应用,避免 address already in use 这类错误,如果不这样做将会消耗操作系统一段时间来解除与 port 的绑定。 使用 socket.socket 创建 socket 后,并不能开始沟通,因为还没有将其绑定到任何地址上面。 在本例中,将使用电脑本地地址 127.0.0.1 和任意 port 8000 server_address = ('127.0.0.1', 8000) server_socket.bind(server_address) 这里将地址设置为 127.0.0.1:8000,这意味着 client 将能够使用该地址向服务器发送数据,如果要向 client 发送数据,也会看到该地址为来源地址。 接下来,在套接字上调用 listen 方法,主动监听来自客户端的连接请求。 随后,通过调用 accept 方法等待连接建立。 该方法会保持阻塞状态直至接收到连接请求,当连接成功时,将返回一个连接对象及客户端地址。 这个连接对象本质上是一个新的套接字,可以用于与客户端进行双向数据通信 server_socket.listen() connection, client_address = server_socket.accept() 有了这些组件,我们便掌握了创建基于套接字的服务器应用所需的所有基础模块。 该应用将等待连接,并在建立连接后打印提示信息。 ...

December 1, 2025 · 10 min · 1975 words · Starslayerx

Docker Context

Docker Context 是 Docker 2019 年引入的一个特性,用来管理多个 Docker 主机的上下文,通过切换 context 就能让本地的 docker 命令作用在不同的 Docker 主机上。 本地开发机: docker context use default 远程服务器要配置好 ssh 免密登陆,然后使用下面命令添加 context: docker context create my-server --docker "host=ssh://root@1.2.3.4" docker context create my-server --docker "host=ssh://CompanyServer1" 这里的 CompanyServer1 是 ssh 配置,例如这样 Host CompanyServer1 Hostname 192.168.0.106 User root Port 22 IdentityFile ~/.ssh/id_rsa_company 其中 IdentityFile 是存放无密码密钥的地方,如果你的密钥密钥密码就不需要这一行,否则需要设置一个没有密码的密钥,例如这样 ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa_company -N "" 配置好后就可以在本地连接服务器 docker 了 docker context list 输出类似这样 NAME DESCRIPTION DOCKER ENDPOINT ERROR company-server ssh://CompanyServer1 default Current DOCKER_HOST based configuration unix:///***/docker.sock desktop-linux * Docker Desktop unix:///***/docker.sock 使用命令 use 切换 context ...

November 25, 2025 · 1 min · 122 words · Starslayerx

FastAPI app and request

在 FastAPI 中,Request 对象和 FastAPI 应用实例 (app) 是核心概念,它们在应用状态管理和依赖注入中扮演着关键角色。 本文将介绍它们的关系、设计理念,以及如何利用 app.state 实现单例模式。 FastAPI 对象 FastAPI 对象是整个应用的核心实例: from fastapi import FastAPI app = FastAPI(title="示例应用") 核心职责 路由管理:通过 @app.get()、@app.post() 等装饰器定义 URL 到视图函数的映射。 中间件和事件管理:可注册中间件处理请求/响应,支持 startup 与 shutdown 事件。 应用状态管理:提供 app.state,可存放全局单例对象、数据库连接池、配置等。 异常处理与依赖注入:管理异常处理器,并协助依赖注入机制。 单例模式存储 这里要使用 app 的 State 对象存储单例,app 中定义如下 # app self.state: Annotated[ State, Doc( """ A state object for the application. This is the same object for the entire application, it doesn't change from request to request. You normally wouldn't use this in FastAPI, for most of the cases you would instead use FastAPI dependencies. This is simply inherited from Starlette. Read more about it in the [Starlette docs for Applications](https://www.starlette.dev/applications/#storing-state-on-the-app-instance). """ ), ] = State() State 源码如下,简单看就是一个字典 ...

November 25, 2025 · 2 min · 388 words · Starslayerx

Python Asyncio 02: Asyncio Basics Part 2

Tasks, coroutines, furtures, and awaitables Coroutines 和 tasks 都是 await 表达式,那他们的相同线程是哪个? 下面介绍 future 也被称作 awaitable,理解 futures 是理解 asyncio 内部工作的重点。 Introducing futures Future 代表一个尚未完成的异步操作的最终结果。 from asyncio import Future my_future = Future() print(f"Is my_future done? {my_future.done()}") my_future.set_result(42) print(f"Is my_future done? {my_future.done()}") print(f"What is the result of my_future? {my_future.result()}") 输出为 Is my_future done? False Is my_future done? True What is the result of my_future? 42 使用构造器 Future 来创建 future,这时 future 没有值,因此调用 done 结果是 False。 然后使用 set_result 设置值,这将 future 标记为 done。 相似的,如果想要在 future 中设置异常,使用 set_exception 方法。 ...

November 21, 2025 · 5 min · 1049 words · Starslayerx

Python Asyncio 02: Asyncio Basics Part 1

Introducing coroutines 创建一个协程 coroutine 而不是创建一个函数类型,使用 async def 关键字,而不是 def: async def coroutine_add_one(number: int) -> int: return number + 1 def add_one(number: int) -> int: return number + 1 function_result = add_one(1) coroutine_result = coroutine_add_one(1) print(f"Function result is {function_result} and the type is {type(function_result)}") print(f"Coroutine result is {coroutine_result} and the type is {type(coroutine_result)}") 输出如下 Function result is 2 and the type is <class 'int'> Coroutine result is <coroutine object coroutine_add_one at 0x103000a00> and the type is <class 'coroutine'> 可以看到,协程返回的不是值,而是一个协程对象。 这里协程并没有执行,而是创建了一个协程对象可在之后运行,要运行一个协程则必须显式地在一个事件循环中运行它。 在 Python 3.7 之后的版本,必须创建事件循环来运行它。 asyncio 库添加了多个函数,抽象了事件循环的管理,例如 asyncio.run(),可以使用它来运行协程: ...

November 20, 2025 · 3 min · 637 words · Starslayerx

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