2026年02月25日 星期三 阴

缘起

上午同事找我了两次,说我软件有问题。我听完需求,回到座位一看,我最新软件是好的。第二次是他不懂得配置软件。

我想了一下,以后提醒他们用最新软件好了,我在每次软件运行的时候添加软件版本检测。于是用AI花了一天的时间写完并部署到Pythonanywhere了。主要坑点是fastapi是asgi的,而Pythonanywhere是老牌站点,支持的是wsgi。AI引导我搞得乱七八糟,后来AI不经意发现官方文档,我要求AI遵循官方指南,AI才引导我部署成功。部署花了我60%的时间,所以写下此文记录一下。

说到免费的支持python的服务器,除了PythonAnywhere外,我觉得Render(今天没选是看到它好像有个间歇性休眠的问题)、Oracle Cloud Free Tier下次可以尝试一下。

今天还第一次感受了FastAPI,它自动支持swagger,感觉很好。我们要多接触一些现代化的东西,下面看正文:

最近在 PythonAnywhere 上部署 FastAPI 时踩了不少坑,最终通过官方的 ASGICommandLine 方案 成功解决了所有问题。本文将完整梳理部署流程,包括准备工作、具体步骤、常见问题及解决方案,帮助大家快速上手。

为什么选择 PythonAnywhere + FastAPI?

  • PythonAnywhere :免费、易用,适合部署小型 Python Web 应用,支持虚拟环境和自定义域名。
  • FastAPI :高性能、异步支持、自动生成 API 文档,是现代 Python Web 开发的热门选择。
  • 官方 ASGI 方案 :PythonAnywhere 提供的实验性 ASGI 部署方式,直接托管 uvicorn 运行 FastAPI,无需复杂的转发配置,稳定可靠。

参考文献PythonAnywhere ASGICommandLine 官方文档


准备工作

1. 注册 PythonAnywhere 账号

访问 PythonAnywhere 官网 注册免费账号,注册后会自动分配一个子域名(如 yourusername.pythonanywhere.com)。

2. 创建虚拟环境并安装依赖

打开 PythonAnywhere 的 Bash 终端,执行以下命令:

bash

运行

# 创建 Python 3.10 虚拟环境
mkvirtualenv my_venv --python=python3.10

# 激活虚拟环境
workon my_venv

# 安装 FastAPI 和 uvicorn
pip install "uvicorn[standard]" fastapi

# 安装项目依赖(根据你的项目补充)
pip install sqlalchemy python-multipart jinja2

3. 生成 API Token

官方 ASGI 方案需要通过 API Token 连接 PythonAnywhere,步骤如下:

  1. 点击右上角「Account」→「API token」;
  2. 点击「Create a new API token」;
  3. 复制生成的 token(格式类似 1234567890abcdef1234567890abcdef)。

在 Bash 终端配置 API Token:(根据官方指南,只需要生成token就行了,下面这步应该不需要。

bash运行

export PA_API_TOKEN="你的API_TOKEN"

具体部署步骤

1. 删除旧的 Web app(避免冲突)

如果之前在「Web」页面创建过旧的 WSGI 模式 app,先删除:

  1. 打开「Web」页面;
  2. 找到旧 app,点击底部「Delete web app」→ 确认删除。

2. 准备 FastAPI 项目

确保你的项目结构如下(以本文的 Pulse 项目为例):

plaintext

Pulse/
├── main.py          # FastAPI 主文件
├── templates/       # 模板目录
│   ├── login.html   # 登录页面
│   └── admin.html   # 后台页面
└── pulse.db         # 数据库文件(可选,会自动创建)

关键修改 :将 main.py 中的模板目录改为 绝对路径 (避免找不到模板):

python

运行

from fastapi.templating import Jinja2Templates

# 错误:相对路径,部署后会找不到模板,官方好像有说配置静态文件好像有问题,我就临时解决一下
# templates = Jinja2Templates(directory="templates")

# 正确:绝对路径,替换为你的项目实际路径
templates = Jinja2Templates(directory="/home/yourusername/tktools/app/Pulse/templates")

3. 用 pa 命令创建 ASGI 网站

在 Bash 终端执行( 替换 yourusername 为你的 PythonAnywhere 用户名 ):

bash

运行

# 激活虚拟环境
workon my_venv

# 创建 ASGI 网站
pa website create \
  --domain yourusername.pythonanywhere.com \
  --command '/home/yourusername/.virtualenvs/my_venv/bin/uvicorn --app-dir /home/yourusername/tktools/app/Pulse --uds ${DOMAIN_SOCKET} main:app'

命令详解

  • --domain:你的网站域名;
  • --command:启动命令,核心参数说明:
    • /home/yourusername/.virtualenvs/my_venv/bin/uvicorn:虚拟环境中 uvicorn 的绝对路径;
    • --app-dir:FastAPI 项目的根目录(main.py 所在目录);
    • --uds ${DOMAIN_SOCKET}:官方要求的 Unix Socket 监听方式, 禁止替换为 --bind 端口模式
    • main:app:FastAPI 实例入口,对应 main.pyapp = FastAPI() 的实例名。

4. 验证网站创建成功

执行以下命令查看已创建的 ASGI 网站:

bash

运行

pa website get

终端输出你的域名和启动命令,即代表创建成功。

5. 重启并验证部署结果

bash

运行

# 重启网站,加载最新代码
pa website reload --domain yourusername.pythonanywhere.com

# 查看启动日志,确认服务正常运行
tail -50 /var/log/yourusername.pythonanywhere.com.server.log

成功启动日志示例

plaintext

INFO:     Started server process [1]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on unix socket /var/sockets/yourusername.pythonanywhere.com/app.sock (Press CTRL+C to quit)

访问以下地址验证功能:

  • FastAPI 自动文档:https://yourusername.pythonanywhere.com/docs
  • 自定义页面:https://yourusername.pythonanywhere.com/login
  • 健康检查接口:https://yourusername.pythonanywhere.com/health

常见问题及解决方案

1. 模板找不到报错:jinja2.exceptions.TemplateNotFound: login.html

核心原因Jinja2Templates 使用了相对路径,--app-dir 启动时无法正确定位模板目录。

解决方案 :将模板目录路径改为服务器上的 绝对路径 ,参考上文「准备 FastAPI 项目」部分的代码修改。

2. hypercorn 导入错误:ModuleNotFoundError: No module named 'hypercorn.wsgi'

核心原因 :hypercorn 版本适配问题,或 WSGI 转 ASGI 方案的兼容性缺陷。

解决方案 :放弃 hypercorn 适配方案,直接使用本文推荐的官方 ASGICommandLine 原生 uvicorn 部署方案,无需任何适配层。

3. 日志中仍出现旧的 uWSGI 启动信息

核心原因 :旧的 WSGI 模式 Web app 未完全删除,域名被占用。

解决方案 :进入「Web」页面,确认所有旧 app 已删除,重新执行 pa website create 命令创建 ASGI 网站。

4. ASGI 网站不在「Web」页面显示

核心原因 :官方明确说明 ASGI 部署为实验性功能,暂不支持在 Web 页面可视化管理。

解决方案 :正常现象,无需处理。所有管理操作通过 pa 命令行完成,直接访问域名即可使用服务。

5. 修改代码后不生效

核心原因 :代码修改后未重启 ASGI 网站,服务仍运行旧版本代码。

解决方案 :执行 pa website reload --domain yourusername.pythonanywhere.com 重启服务,加载最新代码。


常用 pa 命令汇总

表格

操作 命令
查看所有 ASGI 网站 pa website get
查看指定网站详情 pa website get --domain yourusername.pythonanywhere.com
重启网站(更新代码) pa website reload --domain yourusername.pythonanywhere.com
删除网站 pa website delete --domain yourusername.pythonanywhere.com
为自定义域名申请 SSL 证书 pa website create-autorenew-cert --domain yourcustomdomain.com

总结

PythonAnywhere 的 ASGICommandLine 方案 是部署 FastAPI 的最优选择,它:

  • ✅ 无需复杂的 WSGI 转发 / 适配代码,原生支持 ASGI 应用;
  • ✅ 直接托管 uvicorn 进程,无端口冲突、协议兼容问题;
  • ✅ 完整支持 FastAPI 异步特性、模板渲染、接口文档等所有功能;
  • ✅ 免费账号即可使用,无额外配置门槛。

只要按照本文的步骤操作,重点注意模板路径使用绝对路径,就能快速完成 FastAPI 的部署上线。

官方参考文档PythonAnywhere ASGICommandLine 官方文档