1. 什么是 uvicorn? #

uvicorn 是一个用来「运行」Python Web 应用的服务器程序。你写好一个 Web 应用(比如用 FastAPI 写的接口),需要有一个程序来接收 HTTP 请求、把请求交给你的代码处理、再把响应返回给用户——这个程序就是 uvicorn。

为什么需要 uvicorn?

2. 前置知识 #

在学 uvicorn 之前,建议先了解这些概念(不懂也没关系,可以边学边查):

Web 应用与 Web 服务器

ASGI 是什么?

FastAPI 简介

3. 安装 #

在命令行中执行:

pip install uvicorn

如果要用 FastAPI,需要一起安装:

pip install uvicorn fastapi

安装完成后,可以用命令行 uvicorn 或 Python 代码来启动服务器。

4. 第一个应用:最简 ASGI 应用 #

下面是一个最简单的 ASGI 应用,用来理解 uvicorn 在做什么。

步骤 1:新建文件 app.py,写入以下代码:

# 这是一个最简的 ASGI 应用
# scope:请求信息(路径、方法等)
# receive:接收请求体的函数
# send:发送响应的函数
async def app(scope, receive, send):
    # 只处理 HTTP 请求
    assert scope["type"] == "http"
    # 发送响应头:状态码 200,内容类型为纯文本
    await send({
        "type": "http.response.start",
        "status": 200,
        "headers": [(b"content-type", b"text/plain; charset=utf-8")],
    })
    # 发送响应体:Hello, uvicorn!
    await send({
        "type": "http.response.body",
        "body": b"Hello, uvicorn!",
    })

步骤 2:在终端进入 app.py 所在目录,执行:

uvicorn app:app

步骤 3:打开浏览器访问 http://127.0.0.1:8000,会看到 Hello, uvicorn!。

命令解释:app:app 表示「从 app 模块(即 app.py)中加载名为 app 的变量(即上面的异步函数)」。

5. 理解 uvicorn 命令格式 #

uvicorn 的命令格式是:

uvicorn 模块名:应用变量名

示例:

6. 常用命令行选项 #

开发时常用的几个参数如下。

参数 说明 示例
--host 绑定的地址 --host 0.0.0.0 允许外网访问
--port 端口号,默认 8000 --port 8080
--reload 文件改动时自动重启 --reload(仅开发时用)

完整示例:在 8080 端口启动,并开启自动重载:

uvicorn app:app --host 127.0.0.1 --port 8080 --reload

7. 运行 FastAPI 应用 #

FastAPI 应用也是 ASGI 应用,可以直接用 uvicorn 运行。下面是一个完整可运行的例子。

步骤 1:新建 main.py,写入:

# 导入 FastAPI
from fastapi import FastAPI

# 创建 FastAPI 应用实例
app = FastAPI()


# 定义根路径 / 的 GET 接口,返回 JSON
@app.get("/")
async def root():
    return {"message": "Hello World", "framework": "FastAPI"}


# 定义 /hello/{name} 路径,name 为路径参数
@app.get("/hello/{name}")
async def say_hello(name: str):
    return {"message": f"你好, {name}!"}

步骤 2:在终端执行:

uvicorn main:app --reload

步骤 3:测试接口

8. 用 Python 代码启动 uvicorn #

除了命令行,也可以在 Python 脚本里启动 uvicorn,适合写启动脚本或做简单测试。

示例 1:用字符串指定应用

# 导入 uvicorn
import uvicorn

# 当直接运行此脚本时启动服务器
if __name__ == "__main__":
    # 第一个参数:模块名:应用变量名,用字符串
    # host:监听地址
    # port:端口
    # reload:开发时自动重载
    uvicorn.run(
        "main:app",
        host="127.0.0.1",
        port=8000,
        reload=True,
    )

示例 2:先导入应用对象再传入

# 导入 uvicorn 和你的 FastAPI 应用
import uvicorn
from main import app

if __name__ == "__main__":
    # 直接传入应用对象(不能与 reload 同时使用)
    uvicorn.run(app, host="127.0.0.1", port=8000)

注意:使用 reload=True 时,第一个参数必须是字符串(如 "main:app"),不能是已导入的应用对象。

9. 可独立运行的项目 #

下面是一个包含应用和启动脚本的完整示例。

文件 1:demo_app.py(FastAPI 应用)

# 导入 FastAPI
from fastapi import FastAPI

# 创建应用
app = FastAPI(title="uvicorn 入门示例")


# 根路径
@app.get("/")
async def index():
    return {"status": "ok", "msg": "欢迎使用 uvicorn"}


# 健康检查接口
@app.get("/health")
async def health():
    return {"status": "healthy"}

文件 2:run.py(启动脚本)

# 导入 uvicorn
import uvicorn

if __name__ == "__main__":
    # 启动 demo_app 模块中的 app
    uvicorn.run(
        "demo_app:app",
        host="127.0.0.1",
        port=8000,
        reload=True,
    )

运行方式:在项目目录下执行 python run.py,然后访问 http://127.0.0.1:8000 和 http://127.0.0.1:8000/health。

10. 常见问题 #

10.1 如何让局域网内其他电脑访问? #

使用 --host 0.0.0.0,表示监听所有网卡:

uvicorn main:app --host 0.0.0.0 --port 8000

然后其他电脑通过 http://你的IP:8000 访问。

10.2 修改代码后如何自动重启? #

加 --reload 参数即可。注意:生产环境不要使用 --reload。

uvicorn main:app --reload

10.3 如何换一个端口? #

使用 --port,例如:

uvicorn main:app --port 8080

10.4 启动时报错 ModuleNotFoundError? #

说明 Python 找不到你的模块,请确认:

11. 总结 #

12. 参考资料 #