FastAPI 零基础入门教程:写过 Node.js,就能轻松学会 Python 后端开发(一)

2026 版

Node.js 开发者转 Python

包含完整 CRUD 实战

这篇文章专门写给有 Node.js、Express、NestJS 开发经验,但刚开始学习 Python FastAPI 的开发者。

核心思路:不从 Python 基础语法开始讲,而是直接拿 Node.js 对比 FastAPI,让你用熟悉的开发思维快速上手。

学完这篇文章,你将能够:

  • 理解 FastAPI、Express、NestJS 的关系。
  • 使用 Python 创建 HTTP API 服务。
  • 掌握 GET、POST、PUT、DELETE 请求。
  • 理解 Python 类型注解、Pydantic 数据校验。
  • 使用 SQLite 实现真正的数据库 CRUD。
  • 学会项目目录组织、异步编程、接口文档和测试。

一、FastAPI 到底是什么?

先看一个概念:

FastAPI 是一个使用 Python 编写的现代 Web API 框架。

如果你以前使用过 Express,那么可以这样理解:

Node.js 生态 Python 生态 作用
Node.js Python 运行环境
npm / pnpm pip / uv 包管理
Express FastAPI Web API 框架
NestJS FastAPI + 分层架构 组织后端业务
TypeScript Python 类型注解 类型声明
Zod / class-validator Pydantic 数据校验
Prisma / TypeORM SQLModel / SQLAlchemy ORM
nodemon fastapi dev 开发热重载
Swagger FastAPI 内置 OpenAPI API 文档

FastAPI 有几个非常实用的特点:

  1. 代码简洁: 不需要大量配置就可以创建 API。
  2. 自动参数校验: 请求参数类型不对,框架自动返回错误。
  3. 自动生成 API 文档: 不需要额外安装 Swagger。
  4. 支持 async / await: 可以处理异步 I/O 操作。
  5. 类型提示友好: VS Code、PyCharm 等编辑器可以获得良好的自动补全。

FastAPI 基于 Starlette 和 Pydantic,数据库层不绑定特定 ORM,可以按项目需求选择。

GitHub

+1

二、Express 和 FastAPI 代码对比

先不安装环境,直接看代码。

Node.js + Express

JavaScript

javascript 复制代码
import express from "express";

const app = express();

app.get("/hello", (req, res) => {
  res.json({
    message: "Hello World"
  });
});

app.listen(3000, () => {
  console.log("Server running");
});
  

Python + FastAPI

Python

csharp 复制代码
from fastapi import FastAPIapp = FastAPI()@app.get("/hello")def hello():    return {        "message": "Hello World"    }  

两个框架做的是同一件事:接收 /hello 请求,返回 JSON。

主要区别:

  • Express 通过 app.get() 注册回调。
  • FastAPI 使用 @app.get() 装饰器定义路由。
  • Express 通过 res.json() 返回数据。
  • FastAPI 直接 return Python 字典,框架会自动转换为 JSON。

可以把 @app.get() 理解为 Express 的路由注册语法。

三、搭建 FastAPI 开发环境

这里以 macOS 为例,Windows 和 Linux 的开发流程基本一致。

1. 检查 Python

打开终端:

css 复制代码
python3 --version

建议使用 Python 3.12 或更新的稳定版本。本文代码使用 Python 3.10+ 的类型语法。

2. 安装 uv

如果你熟悉 pnpm,那么建议了解一下 uv。

它是一个 Python 项目与依赖管理工具,可以帮助你创建虚拟环境、安装依赖、锁定版本和运行程序。

macOS 使用 Homebrew 安装:

复制代码
brew install uv

检查:

css 复制代码
uv --version

3. 创建项目

直接复制执行:

csharp 复制代码
# 创建 Python 项目
uv init fastapi-demo --bare

# 进入项目
cd fastapi-demo

# 安装 FastAPI 和标准开发依赖
uv add "fastapi[standard]"

# 检查环境
uv run python --version

这和 Node.js 中的以下操作非常相似:

bash 复制代码
mkdir express-demo
cd express-demo

npm init -y
npm install express

官方也推荐使用 uv 创建项目、管理依赖和运行 FastAPI。

GitHub

+1

4. 认识目录

csharp 复制代码
fastapi-demo/
├── .venv/           # Python 虚拟环境
├── .python-version   # Python 版本(如有)
├── pyproject.toml    # 类似 package.json
├── uv.lock           # 类似 pnpm-lock.yaml
└── main.py           # 程序入口(下一步创建)

其中:

  • pyproject.toml:项目名称、依赖、配置。
  • uv.lock:记录锁定的依赖版本。
  • .venv:项目隔离的 Python 环境。
  • main.py:FastAPI 入口文件。

可以把 .venv 理解为 Node 开发时的项目依赖隔离环境,不过它不等同于 node_modules。

四、创建第一个 FastAPI 服务

在项目根目录创建 main.py:

csharp 复制代码
from fastapi import FastAPIapp = FastAPI(    title="我的第一个 FastAPI 项目",    description="Node.js 开发者学习 FastAPI",    version="1.0.0")@app.get("/")def index():    return {        "code": 200,        "message": "FastAPI 启动成功",        "data": {            "framework": "FastAPI",            "language": "Python"        }    }

运行:

arduino 复制代码
uv run fastapi dev main.py

终端将启动开发服务器,通常访问地址为 http://127.0.0.1:8000。

打开浏览器:

arduino 复制代码
http://127.0.0.1:8000

返回:

css 复制代码
{
  "code": 200,
  "message": "FastAPI 启动成功",
  "data": {
    "framework": "FastAPI",
    "language": "Python"
  }
}

FastAPI 最方便的功能:自动生成 API 文档

Swagger UI 接口文档

自动生成

realpython.com

FastAPI 的 Swagger UI 文档界面示意

http://127.0.0.1:8000/docs

复制地址

启动后可以访问三个地址:

地址 用途
/docs Swagger UI,支持在线调试
/redoc ReDoc API 文档
/openapi.json OpenAPI 接口描述

这一点对于开发前后端分离项目很方便。

五、学习 FastAPI 路由

对于写过 Express 的开发者,路由几乎没有学习成本。

1. GET 请求

Express:

javascript 复制代码
app.get("/users", (req, res) => {
  res.json(["张三", "李四"]);
});

FastAPI:

kotlin 复制代码
@app.get("/users")def get_users():    return ["张三", "李四"]

2. POST 请求

FastAPI 推荐使用 Pydantic 模型定义请求体:

python 复制代码
from pydantic import BaseModelclass UserCreate(BaseModel):    name: str    age: int@app.post("/users")def create_user(user: UserCreate):    return {        "message": "创建成功",        "user": user    }

前端请求:

php 复制代码
await fetch("http://127.0.0.1:8000/users", {
  method: "POST",
  headers: {
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    name: "张三",
    age: 25
  })
});

你可以把:

python 复制代码
class UserCreate(BaseModel):    name: str    age: int

理解为 TypeScript 的接口类型声明加上运行时的 Zod 数据校验。

当传入:

json 复制代码
{
  "name": "张三",
  "age": "abc"
}

FastAPI 会检测到 age 不能解析为整数,并返回 HTTP 422 校验错误。

这意味着很多以前在 Express 中需要手动编写的参数校验逻辑,可以直接交给 Pydantic。

3. 路径参数

Express:

ini 复制代码
app.get("/users/:id", (req, res) => {
  const id = Number(req.params.id);
  res.json({ id });
});

FastAPI:

python 复制代码
@app.get("/users/{id}")def get_user(id: int):    return {"id": id}

访问:

bash 复制代码
GET /users/100

返回:

json 复制代码
{"id": 100}

id: int 表示该参数必须能够解析成整数。

4. Query 查询参数

Express:

ini 复制代码
app.get("/search", (req, res) => {
  const keyword = req.query.keyword;
  res.json({ keyword });
});

FastAPI:

kotlin 复制代码
@app.get("/search")def search(keyword: str = ""):    return {        "keyword": keyword    }

访问:

ini 复制代码
GET /search?keyword=python

返回:

json 复制代码
{"keyword": "python"}

5. PUT 和 DELETE

python 复制代码
@app.put("/users/{id}")def update_user(id: int, user: UserCreate):    return {        "id": id,        "user": user    }@app.delete("/users/{id}")def delete_user(id: int):    return {        "message": f"用户 {id} 已删除"    }

到这里你已经掌握 FastAPI 最基本的路由开发。

六、Python 语法:Node.js 开发者只需要先掌握这些

JavaScript / TypeScript Python
const name = "Tom" name = "Tom"
let age = 20 age = 20
function add(a, b) {} def add(a, b):
console.log("Hello") print("Hello")
true / false True / False
null None
a === b a == b
!value not value
a && b a and b
`a
array.map(...) 列表推导式或 map()
try / catch try / except
import x from "x" import x / from x import y

Python 使用缩进组织代码

JavaScript:

javascript 复制代码
function getName(name) {
  if (name) {
    return name;
  }
  return "Unknown";
}

Python:

kotlin 复制代码
def get_name(name):    if name:        return name    return "Unknown"

Python 没有 {} 包围代码块,而是使用缩进。

建议统一使用四个空格。

Python 类型注解

TypeScript:

typescript 复制代码
function add(a: number, b: number): number {
  return a + b;
}

Python:

php 复制代码
def add(a: int, b: int) -> int:    return a + b

需要注意:Python 的类型注解默认不会像 TypeScript 编译器那样进行强制静态检查。 FastAPI 会根据声明的接口参数类型执行验证和转换,而普通 Python 函数则不会自动验证类型。

Python 类

TypeScript:

typescript 复制代码
class User {
  constructor(
    public name: string,
    public age: number
  ) {}
}

Python:

python 复制代码
class User:    def __init__(self, name: str, age: int):        self.name = name        self.age = age

self 类似 JavaScript 类中的 this。

理解这些语法后,阅读大部分 FastAPI 入门代码不会太困难。

七、实战:开发一个真正的用户管理 API

前面只是基本路由。接下来我们做一个可以运行的项目。

实现的功能包括:

  • 新增用户
  • 查询用户列表
  • 查询单个用户
  • 修改用户
  • 删除用户
  • SQLite 数据库存储
  • 自动生成接口文档

这相当于一个简化版的 Express + Prisma 用户管理系统。

1. 安装数据库依赖

这里使用 SQLModel。

它结合了 SQLAlchemy 和 Pydantic,既能描述数据库表,也能支持类型校验。FastAPI 官方的 SQL 数据库教程也使用 SQLModel 作为示例。

FastAPI

+1

在刚才的项目目录执行:

csharp 复制代码
uv add sqlmodel

SQLite 是 Python 自带支持的数据库,入门阶段不需要安装 MySQL 或 PostgreSQL。

2. 创建完整项目代码

把 main.py 替换为以下代码。这是一套完整、可运行的 CRUD 示例。

sql 复制代码
from contextlib import asynccontextmanagerfrom typing import Annotatedfrom fastapi import Depends, FastAPI, HTTPException, Queryfrom pydantic import BaseModel, ConfigDict, Fieldfrom sqlmodel import (    Field as SQLField,    Session,    SQLModel,    create_engine,    select,)# ========== 1. 数据库配置 ==========sqlite_url = "sqlite:///./database.db"engine = create_engine(    sqlite_url,    connect_args={"check_same_thread": False})# ========== 2. 数据库表 ==========class User(SQLModel, table=True):    id: int | None = SQLField(        default=None,        primary_key=True    )    name: str    age: int    email: str

本例为了方便入门,把所有逻辑放在一个文件中。数据库的 email 暂时只验证最小长度,并没有做邮箱格式校验或唯一性约束,后面可以进一步完善。

3. 启动项目

执行:

arduino 复制代码
uv run fastapi dev main.py

第一次启动后,项目目录会新增:

csharp 复制代码
fastapi-demo/
├── .venv/
├── pyproject.toml
├── uv.lock
├── main.py
└── database.db

database.db 就是 SQLite 数据库文件。

4. 测试 CRUD

直接访问:

arduino 复制代码
http://127.0.0.1:8000/docs

也可以使用终端测试。

创建用户

arduino 复制代码
curl -X POST http://127.0.0.1:8000/users \
  -H "Content-Type: application/json" \
  -d '{
    "name": "张三",
    "age": 25,
    "email": "zhangsan@example.com"
  }'
  

预期返回:

perl 复制代码
{
  "id": 1,
  "name": "张三",
  "age": 25,
  "email": "zhangsan@example.com"
}

继续测试:

查询用户列表

arduino 复制代码
curl http://127.0.0.1:8000/users
  

查询指定用户

arduino 复制代码
curl http://127.0.0.1:8000/users/1
  

修改用户年龄

json 复制代码
curl -X PATCH http://127.0.0.1:8000/users/1 \
  -H "Content-Type: application/json" \
  -d '{"age": 26}'
  

删除用户

arduino 复制代码
curl -X DELETE http://127.0.0.1:8000/users/1
  

至此,一个真正将数据保存到数据库中的 REST API 已经完成。

5. 理解数据库代码

如果以前用过 Prisma,这段逻辑应该很好理解。

SQLModel / FastAPI Prisma / Node.js
session.add(user) prisma.user.create() 的部分操作
session.commit() 提交数据库事务
session.refresh(user) 从数据库刷新对象
session.get(User, id) prisma.user.findUnique()
select(User) prisma.user.findMany()
session.delete(user) prisma.user.delete() 的部分操作

注意,ORM 的接口并不是一一对应。SQLModel 使用显式 Session 管理事务,而 Prisma Client 通常把创建、更新等操作封装成方法调用。

八、理解 Depends:FastAPI 的依赖注入

你可能注意到代码里有:

ini 复制代码
SessionDep = Annotated[    Session,    Depends(get_session)]

这是什么?

可以把它理解成:每次请求进入路由时,FastAPI 自动准备一个数据库 Session,路由执行结束后再关闭它。

一次请求中的数据库依赖生命周期

在 Express 中,我们可能手动获取数据库连接并释放:

dart 复制代码
app.get("/users", async (req, res) => {
  const users = await prisma.user.findMany();
  res.json(users);
});

在 FastAPI 中,常见写法是:

less 复制代码
@app.get("/users")def get_users(session: SessionDep):    return session.exec(select(User)).all()

不必在每个路由中重复编写创建和关闭 Session 的代码。

Depends() 不只用于数据库,也可以管理:

  • JWT 用户认证
  • 登录权限判断
  • 配置读取
  • 公共参数处理
  • 服务对象注入

它在 FastAPI 中非常重要。

九、async / await:和 Node.js 有什么区别?

对于 Node.js 开发者,这也是必须理解的部分。

Node.js 异步代码

csharp 复制代码
async function getUser() {
  const response = await fetch(
    "https://example.com/api/user"
  );

  return await response.json();
}

FastAPI 异步代码

csharp 复制代码
import httpx@app.get("/external-user")async def get_external_user():    async with httpx.AsyncClient() as client:        response = await client.get(            "https://example.com/api/user"        )        response.raise_for_status()        return response.json()

需要先安装:

csharp 复制代码
uv add httpx

这里的 https://example.com/api/user 是演示地址,并不是可用的真实 API。

两者的 async / await 编写体验相似,但运行时机制并不完全相同。

什么时候用 async def?

场景 建议
异步 HTTP 请求 async def
异步数据库驱动 async def
WebSocket async def
同步 SQLModel Session 普通 def
同步文件库或同步 SDK 通常使用普通 def
大量 CPU 密集计算 独立进程或任务执行器

重要:不是所有 FastAPI 路由都应该写成 async def。

FastAPI 可以把普通同步路由放在线程池执行。对于同步数据库调用,通常使用 def 更合适。

如果在 async def 路由中直接执行长时间的同步阻塞操作,反而可能阻塞事件循环。

十、配置跨域 CORS

你以前使用 Vue、React 调用 Express API 时,应该用过 cors。

Express:

php 复制代码
import cors from "cors";

app.use(cors({
  origin: ["http://localhost:5173"]
}));

FastAPI:

css 复制代码
from fastapi.middleware.cors import CORSMiddlewareapp.add_middleware(    CORSMiddleware,    allow_origins=["http://localhost:5173"],    allow_credentials=True,    allow_methods=["*"],    allow_headers=["*"],)

把这段代码放到创建 app 后的位置即可。

这样就允许本地 Vite 前端从 http://localhost:5173 访问 FastAPI。

生产环境应配置实际允许的前端域名,不要随意开放所有来源。

十一、实际开发应该怎样组织目录?

前面我们将路由、数据库、业务代码全部放进 main.py,方便学习,但真正开发时不建议这样组织。

如果你熟悉 NestJS,可以直接采用类似的模块化目录。

推荐的 FastAPI 项目结构

markdown 复制代码
fastapi-demo/
├── app/
│   ├── __init__.py
│   ├── main.py
│   │
│   ├── api/
│   │   ├── __init__.py
│   │   └── users.py
│   │
│   ├── models/
│   │   ├── __init__.py
│   │   └── user.py
│   │
│   ├── schemas/
│   │   ├── __init__.py
│   │   └── user.py
│   │
│   ├── services/
│   │   ├── __init__.py
│   │   └── user_service.py
│   │
│   ├── repositories/
│   │   ├── __init__.py
│   │   └── user_repository.py
│   │
│   ├── core/
│   │   └── config.py
│   │
│   └── db/
│       └── database.py
│
├── tests/
│   └── test_users.py
│
├── .env
├── .gitignore
├── pyproject.toml
└── uv.lock

对应 NestJS:

FastAPI NestJS 职责
main.py main.ts 程序入口
api/users.py users.controller.ts 路由
services/ *.service.ts 业务逻辑
repositories/ Repository 数据访问
schemas/ dto/ 请求、响应校验
models/ entities/ 数据库实体
core/config.py ConfigModule 环境配置
Depends() 依赖注入机制 注入依赖

APIRouter:类似 Express Router

例如 app/api/users.py:

csharp 复制代码
from fastapi import APIRouterrouter = APIRouter(    prefix="/users",    tags=["用户管理"])@router.get("/")def get_users():    return [        {"id": 1, "name": "张三"},        {"id": 2, "name": "李四"}    ]

在 app/main.py 中注册:

javascript 复制代码
from fastapi import FastAPIfrom app.api.users import router as users_routerapp = FastAPI()app.include_router(users_router)

启动:

arduino 复制代码
uv run fastapi dev app/main.py

这样你就把路由模块单独拆分出来了。

更大型的项目可以继续分成 Controller(API 层)、Service(业务层)、Repository(数据访问层)。

不过 FastAPI 没有要求你必须遵守 NestJS 的分层模式,简单项目不必过度设计。

十二、FastAPI 怎么写接口测试?

熟悉 Node.js 的你可能使用过 Jest、Vitest 或 Supertest。

Python 生态里可以使用 pytest,FastAPI 还提供了方便的 TestClient。

先安装:

sql 复制代码
uv add --dev pytest

创建 test_main.py:

csharp 复制代码
from fastapi import FastAPIfrom fastapi.testclient import TestClientapp = FastAPI()@app.get("/hello")def hello():    return {"message": "Hello"}client = TestClient(app)def test_hello():    response = client.get("/hello")    assert response.status_code == 200    assert response.json() == {        "message": "Hello"    }

执行:

arduino 复制代码
uv run pytest -v

这个例子用于学习 HTTP 接口断言。实际项目中应该从应用模块导入 app,并为 CRUD 测试准备独立的测试数据库,避免影响开发数据。

十三、常用命令速查

建议收藏这张表,以后开发时经常会用到。

Node.js Python + uv
npm init -y uv init --bare
npm install express uv add "fastapi[standard]"
npm install axios uv add httpx
npm install -D vitest uv add --dev pytest
npm uninstall axios uv remove httpx
npm install uv sync
npm run dev uv run fastapi dev main.py
npm test uv run pytest
node app.js uv run python app.py

生产环境可以使用:

arduino 复制代码
uv run fastapi run main.py

这是生产运行模式,但真实部署时还需要配置反向代理、HTTPS、进程管理、日志、数据库迁移和健康检查等。

十四、FastAPI、Express、NestJS,究竟怎么选?

对比 Express NestJS FastAPI
语言 JavaScript / TS TypeScript Python
学习成本 低 中 低至中
项目结构 自由 规范化 自由
类型校验 需要额外方案 DTO 等方案 Pydantic
Swagger 通常需要配置 需要集成 自动生成
AI / ML 生态 可以集成 可以集成 Python 生态优势明显
大型业务系统 可以 适合 可以
异步 I/O 支持 支持 支持

对于你这种已经有 Node.js 开发经验的程序员,我建议:

如果是常规企业后台、业务系统和已经成熟的 TypeScript 技术栈,继续使用 NestJS 没问题。

如果要开发 AI Agent、RAG 知识库、Ollama 模型接口、数据处理或者机器学习服务,FastAPI 值得优先学习。

不是 FastAPI 天生比 NestJS 更适合所有后端业务,而是 Python 的 AI 相关工具链非常丰富,可以减少跨语言调用的成本。

十五、实战进阶:FastAPI + Ollama

例如,你希望用 FastAPI 包装一个本地模型接口,让 React、Vue 或其他 Agent 应用统一调用。

假设你的本机已启动 Ollama,并已经下载了一个可用模型,就可以采用下面这种架构:

FastAPI 作为本地 AI 服务的 HTTP 接口层

安装 HTTP 客户端:

csharp 复制代码
uv add httpx

创建 ai_server.py:

python 复制代码
import httpxfrom fastapi import FastAPI, HTTPExceptionfrom pydantic import BaseModelapp = FastAPI(title="本地 AI 服务")class ChatRequest(BaseModel):    message: str    model: str@app.post("/chat")async def chat(payload: ChatRequest):    try:        async with httpx.AsyncClient(            timeout=120        ) as client:            response = await client.post(                "http://127.0.0.1:11434/api/chat",                json={                    "model": payload.model,                    "messages": [                        {                            "role": "user",                            "content": payload.message                        }                    ],                    "stream": False                }            )            response.raise_for_status()

启动:

arduino 复制代码
uv run fastapi dev ai_server.py

调用:

arduino 复制代码
curl -X POST http://127.0.0.1:8000/chat \
  -H "Content-Type: application/json" \
  -d '{
    "message": "介绍一下 FastAPI",
    "model": "llama3.2"
  }'

这里的 llama3.2 只是示例模型名称,必须先通过 ollama list 确认本机存在对应模型。这个示例采用非流式输出,方便理解;后续可以改成 SSE 流式响应。

实际对外部署时,还需要增加用户认证、模型白名单、超时控制和限流等安全机制。

十六、建议学习路线

如果目标是从 Node.js 转向 FastAPI 开发,可以按下面的顺序学习。

FastAPI 学习进度

0 / 6 已完成

第 1 阶段:Python 基础

变量、函数、类、类型注解、异常、async/await

第 2 阶段:FastAPI 基础

路由、请求参数、Pydantic、HTTP 错误、Swagger

第 3 阶段:数据库

SQLite、PostgreSQL、SQLModel、SQLAlchemy、事务

第 4 阶段:工程化

APIRouter、Depends、环境配置、pytest、Alembic 迁移

第 5 阶段:权限与部署

JWT、用户权限、Docker、Nginx、日志、监控

第 6 阶段:AI 项目实战

FastAPI + Ollama + RAG + Agent + SSE 流式响应

十七、推荐的官方学习资料

总结

作为 Node.js 开发者,你可以记住下面五句话:

  1. FastAPI 类似 Express,但更强调 Python 类型注解和自动数据校验。
  2. Pydantic 可以理解为 Python 中的 DTO + Zod。
  3. SQLModel 可以理解为 Python 生态中的 ORM 工具之一。
  4. Depends 是 FastAPI 很重要的依赖注入机制。
  5. uv 可以作为 Python 项目中类似 pnpm 的依赖和运行管理工具。

你已经具备 HTTP、REST API、数据库、异步编程等后端开发基础,不需要从零重新学习后端设计。主要需要适应 Python 语法、Pydantic、依赖注入以及 Python 的运行和包管理方式。

相关推荐
盛世宏博智慧档案1 小时前
恒湿净化一体机联动开发:档案馆温湿度阈值判断与启停控制实践
java·后端·struts·恒湿机·加湿除湿消毒净化一体机
桔筐1 小时前
Vue中DOM的data-*自定义属性(dataset)与Vue data响应式变量区别详解
前端·javascript·vue.js
huaweichenai1 小时前
spring boot实现base64上传
java·spring boot·后端
点纭1 小时前
spring ai1.0实战:ChatClient(2)
java·后端·spring
小马过河R1 小时前
EdgeOne深度解析:从原理、适用场景到COS接入的技术逻辑
java·开发语言·前端·spring·cos
Gopher_HBo1 小时前
Resolver 与 Balancer —— 连接管理三层联动
后端
yunwei371 小时前
eBPF 实例教程:BPF Arena 零拷贝共享内存
linux·后端·性能优化
Marst Code1 小时前
上位机开发日记 · 第 12 篇 · 测试:设备模拟器是核心资产
python
UrbanJazzerati1 小时前
AutoHotkey v2 零基础快速入门 Part 1
后端