- 示例工程
【免费下载链接】python-docs-samples
Code samples used on cloud.google.com
本文围绕开源仓库 python-docs-samples 中的 appengine/flexible/twilio 示例,系统讲解如何在 Google App Engine Flexible Environment(灵活环境)上用 Python 集成 Twilio,实现来电语音应答、主动发送短信与自动回复短信三条完整链路。读者学完后将掌握 Twilio 账号与号码配置、app.yaml环境变量注入、本地调试及gcloud部署的完整流程,并理解底层 Flask 路由与 TwiML 的交互原理。
示例概览:一个 Flask 应用如何同时处理语音与短信
该示例是一个典型的 App Engine Flexible Environment Web 应用,核心是一个基于 Flask 的 HTTP 服务(main.py),对外暴露三个路由,分别对应 Twilio 平台的三种交互场景:
| 路由 | 方法 | 功能 | Twilio 侧对应配置 |
|---|---|---|---|
/call/receive | POST | 应答来电并播放语音问候语 | 号码的 Voice Request URL |
/sms/send | GET | 主动向指定号码发送短信 | 由应用自行触发,无需 Twilio 配置 |
/sms/receive | POST | 接收短信并自动回复一条问候 | 号码的 SMS Request URL |
整体工作流为:Twilio 平台在收到来电或短信时,向你在 Twilio 控制台中配置好的 URL 发起 HTTP 回调;应用收到请求后返回一段 TwiML(Twilio Markup Language)XML,告诉 Twilio 接下来该播放什么语音或回复什么短信。/sms/send则走反向流程,由应用主动调用 Twilio REST API 发起外发短信。
前置准备:Twilio 账号与号码配置
在运行或部署示例之前,需要完成三步准备工作(对应 README 的 Setup 章节):
创建 Twilio 账号。通过 Twilio 面向 Google Cloud 用户的注册入口创建账号,Google App Engine 用户可获得短信与入站消息的赠送额度,可用于降低初期测试成本。
购买并配置一个 Twilio 号码。在 Twilio 控制台创建号码后,需要为该号码设置两个回调 URL:
- Voice Request URL 配置为
https://your-app-id.appspot.com/call/receive - SMS Request URL 配置为
https://your-app-id.appspot.com/sms/receive
其中
your-app-id是部署后 App Engine 应用的 ID(即项目的 appspot.com 域名前缀)。这两个 URL 必须与应用实际部署后的地址一致,否则 Twilio 无法正确回调。- Voice Request URL 配置为
将 Twilio 凭据写入应用配置。也就是下一步要讲的环境变量注入。
配置环境变量:app.yaml中注入 Twilio 凭据
示例的部署配置文件是 app.yaml。该文件同时定义了运行时环境与应用所需的三个环境变量:
runtime: python env: flex entrypoint: gunicorn -b :$PORT main:app runtime_config: python_version: 3 env_variables: TWILIO_ACCOUNT_SID: your-account-sid TWILIO_AUTH_TOKEN: your-auth-token TWILIO_NUMBER: your-twilio-number三个环境变量的含义与取值来源如下:
TWILIO_ACCOUNT_SID:Twilio 账户标识,在 Twilio 控制台 Dashboard 可见,用于标识调用者身份;TWILIO_AUTH_TOKEN:Twilio 账户认证令牌,与 Account SID 配对使用,用于 REST API 调用鉴权,属于敏感凭据;TWILIO_NUMBER:你购买的 Twilio 号码(E.164 格式,如+1xxxxxxxxxx),作为发送短信时的from_号码。
配置中的占位符your-account-sid、your-auth-token、your-twilio-number需要在部署前替换为真实值。入口命令gunicorn -b :$PORT main:app说明应用在 App Engine 上由 Gunicorn WSGI 服务器托管,监听环境变量$PORT指定的端口。值得留意的是,该示例的app.yaml未显式设置manual_scaling与resources字段;对比仓库中 appengine/flexible/hello_world/app.yaml 可以看到,灵活的 App Engine 支持通过manual_scaling、cpu、memory_gb、disk_size_gb等字段控制实例数量与资源规格,在生产或成本敏感场景可按需补充。
在 main.py 中,这三个变量在模块加载时通过os.environ直接读取:
TWILIO_ACCOUNT_SID = os.environ["TWILIO_ACCOUNT_SID"] TWILIO_AUTH_TOKEN = os.environ["TWILIO_AUTH_TOKEN"] TWILIO_NUMBER = os.environ["TWILIO_NUMBER"]这意味着应用启动时环境变量必须已就绪,否则会抛出KeyError导致启动失败。这一设计也提醒开发者:凭据应始终通过环境变量(或 Secret Manager 等更安全的机制)注入,绝不能硬编码进源码。
本地运行:导出环境变量并启动 Flask
该示例支持完全在本地运行和调试,无需真实来电或短信即可验证回调逻辑。步骤为(对应 README 的 Running locally 章节):
参照 顶层 README 完成环境准备:安装 Google Cloud SDK 与 gcloud 工具、执行
gcloud init完成鉴权、克隆仓库,并按 Google Cloud Python 开发环境指引安装依赖。安装示例依赖:
pip install -r requirements.txt导出三个环境变量后启动应用:
export TWILIO_ACCOUNT_SID=[your-twilio-account-sid] export TWILIO_AUTH_TOKEN=[your-twilio-auth-token] export TWILIO_NUMBER=[your-twilio-number] python main.py
应用启动后会监听127.0.0.1:8080(见 main.py 的本地运行入口),并开启 debug 模式。此时可以用 curl 等工具模拟 Twilio 的回调来验证逻辑,例如:
curl -X POST http://localhost:8080/call/receive curl -X POST http://localhost:8080/sms/receive -d "From=5558675309&Body=Hello" curl "http://localhost:8080/sms/send?to=5558675309"源码解析:三个端点的实现与 TwiML 交互
理解 main.py 的实现,是掌握整个示例原理的关键。三个端点分别对应 README 中配置的 Twilio 回调与主动发送逻辑。
应答来电:/call/receive
@app.route("/call/receive", methods=["POST"]) def receive_call(): """Answers a call and replies with a simple greeting.""" response = voice_response.VoiceResponse() response.say("Hello from Twilio!") return str(response), 200, {"Content-Type": "application/xml"}该端点由 Twilio 在号码收到来电时以 POST 方式调用。代码使用twilio.twiml.voice_response.VoiceResponse构造 TwiML,并通过say()指示 Twilio 用 TTS 播放问候语 "Hello from Twilio!"。响应以application/xml内容类型返回,Twilio 解析后即执行语音播放。
主动发送短信:/sms/send
@app.route("/sms/send") def send_sms(): """Sends a simple SMS message.""" to = request.args.get("to") if not to: return ( 'Please provide the number to message in the "to" query string' " parameter." ), 400 client = rest.Client(TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN) rv = client.messages.create(to=to, from_=TWILIO_NUMBER, body="Hello from Twilio!") return str(rv)这是唯一一个由应用主动发起(GET 请求)的端点:从查询参数to读取目标号码,缺少时返回 400 提示;随后用TWILIO_ACCOUNT_SID与TWILIO_AUTH_TOKEN创建 REST 客户端,调用client.messages.create()发送内容为 "Hello from Twilio!" 的短信,from_指定为TWILIO_NUMBER,最后将消息对象的字符串表示返回给调用方。
接收短信并回复:/sms/receive
@app.route("/sms/receive", methods=["POST"]) def receive_sms(): """Receives an SMS message and replies with a simple greeting.""" sender = request.values.get("From") body = request.values.get("Body") message = f"Hello, {sender}, you said: {body}" response = messaging_response.MessagingResponse() response.message(message) return str(response), 200, {"Content-Type": "application/xml"}该端点由 Twilio 在号码收到短信时以 POST 方式回调。From与Body是 Twilio 回调时携带的表单字段,分别表示发送方号码与短信正文。应用构造包含对方号码和原文的回显消息,包装进messaging_response.MessagingResponse,以 XML 返回给 Twilio,由 Twilio 完成自动回复。
错误处理
main.py 还注册了500错误处理器,任何未捕获异常都会记录到日志并返回包含堆栈信息的错误页,便于在生产环境排查。
部署到 App Engine 灵活环境
本地验证通过后即可部署上线,流程与仓库中 App Engine 灵活环境样本的通用部署流程一致(详见 顶层 README):
在 Google Cloud Console 创建项目(App ID 与 Project ID 相同);
执行
gcloud init完成工具初始化与项目选择;在示例目录执行部署命令:
gcloud app deploy部署成功后应用即运行于
your-app-id.appspot.com,随后回到 Twilio 控制台,将号码的 Voice Request URL 与 SMS Request URL 分别指向https://your-app-id.appspot.com/call/receive与https://your-app-id.appspot.com/sms/receive,即可接通真实来电与短信链路。
测试验证:用 pytest 与 responses 模拟回调
仓库为该示例提供了完整的单元测试 main_test.py,用monkeypatch注入假凭据、用responses库拦截 REST API 调用,从而在不触碰真实 Twilio 服务的前提下验证全部逻辑:
test_receive_call:POST/call/receive,断言响应 XML 中包含 "Hello from Twilio!" 语音文本;test_send_sms:先验证不带to参数时返回 400;再通过responses.add()模拟 Twiliomessages.create的 API 响应,验证带to=5558675309时返回 200;test_receive_sms:以表单数据模拟 Twilio 的回调(From与Body),断言返回的回复短信中包含原始正文。
测试依赖定义在 requirements-test.txt(pytest 与 responses),运行测试前需先安装:
pip install -r requirements-test.txt pytest依赖与版本约束
requirements.txt 列出了本示例的运行时依赖:
Flask==3.1.3; python_version >= '3.9' Werkzeug==3.1.8; python_version >= '3.9' gunicorn==23.0.0 twilio==9.0.3- Flask / Werkzeug:Web 框架及其底层 WSGI 工具集,限定 Python 3.9 及以上版本;
- gunicorn:生产级 WSGI 服务器,对应
app.yaml中的entrypoint; - twilio:Twilio 官方 Python SDK,提供 REST 客户端与 TwiML 构造器(
twilio.rest、twilio.twiml.voice_response、twilio.twiml.messaging_response)。
值得注意的是,noxfile_config.py 中该示例仅在 Python 3.10 上执行 CI 测试(其余版本被忽略),且未强制类型注解——这是该仓库对存量示例的统一测试策略,不影响本地任意受支持 Python 版本的运行。
小结
通过本示例可以看到,在 App Engine 灵活环境集成 Twilio 的核心在于三点:一是用app.yaml的env_variables安全注入账号凭据;二是用 Flask 路由 + TwiML 响应正确应答 Twilio 的语音/短信回调;三是利用 Twilio SDK 主动发起外发短信。结合仓库中的 main.py 与 main_test.py,读者可以快速将其扩展为更复杂的语音菜单、短信机器人或通知服务。示例的贡献与授权说明可分别参考仓库根目录的 CONTRIBUTING.md 与 LICENSE。
- 示例工程
【免费下载链接】python-docs-samples
Code samples used on cloud.google.com
相关推荐
在 App Engine 灵活环境中使用 Python 与 Cloud Pub/Sub 收发消息:完整实战指南
在 App Engine 灵活环境中使用 Python 与 Cloud Pub/Sub 收发消息:完整实战指南 本指南以 python docs samples
示例工程在 App Engine 灵活环境中使用 Python 接入 Cloud Datastore 的完整实践指南
在 App Engine 灵活环境中使用 Python 接入 Cloud Datastore 的完整实践指南 本篇技术指南围绕当前仓库 python docs
示例工程App Engine Flexible 环境集成 Google Cloud Storage:Python 文件上传实战指南(python-docs-samples)
App Engine Flexible 环境集成 Google Cloud Storage:Python 文件上传实战指南(python docs sample
示例工程
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考