deploy-pythonanywhere
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseDeploy to PythonAnywhere
部署到PythonAnywhere
Automate Flask deployment to PA free tier via MCP tools. Only one step needs user's hands: install CLI tools in Bash console. Rest is agent-driven.
通过MCP工具将Flask应用自动化部署到PA免费层级。仅需用户手动完成一步:在Bash控制台安装CLI工具。其余步骤均由Agent自动完成。
Pre-flight
部署前准备
Gather before starting:
- App directory — local path containing app.py, templates/, etc.
- App entry point — the Flask import (e.g.
app).from app import app - External CLI tools — any binary the app shells out to (e.g. ). Agent cannot install these.
officecli - Python version — PA system Python (3.10+); no virtualenv needed — flask/openpyxl available in site-packages.
Gate: Items 1-3 confirmed. If app needs CLI tools, tell user to install them in PA Bash console BEFORE agent starts.
开始前请准备好以下内容:
- 应用目录 — 包含app.py、templates/等文件的本地路径。
- 应用入口 — Flask 的导入语句(例如
app)。from app import app - 外部CLI工具 — 应用调用的任何二进制工具(例如 )。Agent无法安装这些工具。
officecli - Python版本 — PA系统自带的Python(3.10+);无需虚拟环境——flask/openpyxl已预装在site-packages中。
检查点: 确认条目1-3已准备完毕。如果应用需要CLI工具,请告知用户在Agent启动前,先在PA的Bash控制台安装这些工具。
User steps (do these first, then hand off to agent)
用户操作步骤(先完成这些,再交由Agent处理)
User opens PA Bash console and runs what applies:
bash
undefined用户打开PA的Bash控制台,运行对应命令:
bash
undefined1. pip install extras (if requirements.txt has packages beyond system site-packages)
1. 安装额外依赖(如果requirements.txt包含系统site-packages之外的包)
pip install --user -r /home/<username>/<app-name>/requirements.txt
pip install --user -r /home/<username>/<app-name>/requirements.txt
2. CLI tools (if app shells out to any)
2. 安装CLI工具(如果应用需要调用外部CLI)
curl -fsSL <install-url> | bash
No virtualenv needed — system Python has flask/openpyxl. Only run these if app needs extra packages or CLI tools.
**Gate:** User confirms `pip install` succeeded (if needed) + CLI tool `--version` works. Then agent takes over.curl -fsSL <install-url> | bash
无需虚拟环境——系统Python已预装flask/openpyxl。仅当应用需要额外包或CLI工具时才运行上述命令。
**检查点:** 用户确认`pip install`执行成功(若需要),且CLI工具的`--version`命令可正常运行。之后由Agent接管后续操作。Agent steps (fully automated via MCP)
Agent操作步骤(通过MCP完全自动化)
Step 1 — Upload code
步骤1 — 上传代码
python
upload_directory(
local_dir_path="<local-app-dir>",
remote_dir_path="/home/<username>/<app-name>"
)Delete stale cache:
python
delete_path("/home/<username>/<app-name>/__pycache__")Gate: shows all expected files; no .
tree("/home/<username>/<app-name>")__pycache__python
upload_directory(
local_dir_path="<local-app-dir>",
remote_dir_path="/home/<username>/<app-name>"
)删除过期缓存:
python
delete_path("/home/<username>/<app-name>/__pycache__")检查点: 显示所有预期文件;无目录。
tree("/home/<username>/<app-name>")__pycache__Step 2 — Create WSGI entry point
步骤2 — 创建WSGI入口文件
Upload WSGI file via :
upload_text_filepython
upload_text_file(
dest_path="/home/<username>/<app-name>/flask_app.py",
content="""
import os, sys
os.environ["PATH"] = os.path.expanduser("~/.local/bin") + os.pathsep + os.environ.get("PATH", "")
sys.path.insert(0, os.path.expanduser("~/<app-name>"))
from app import app as application
"""
)Key rules:
- PATH line mandatory if app uses CLI in
~/.local/bin - before import
sys.path.insert - is what uWSGI expects
as application
Gate: confirms flask_app.py exists.
read_file_or_directory通过上传WSGI文件:
upload_text_filepython
upload_text_file(
dest_path="/home/<username>/<app-name>/flask_app.py",
content="""
import os, sys
os.environ["PATH"] = os.path.expanduser("~/.local/bin") + os.pathsep + os.environ.get("PATH", "")
sys.path.insert(0, os.path.expanduser("~/<app-name>"))
from app import app as application
"""
)关键规则:
- 如果应用使用中的CLI工具,PATH行必须保留
~/.local/bin - 导入语句前需添加
sys.path.insert - uWSGI要求必须使用命名
as application
检查点: 确认flask_app.py已存在。
read_file_or_directoryStep 3 — Create webapp
步骤3 — 创建Web应用
python
create_webapp(
domain="<username>.pythonanywhere.com",
python_version="3.12",
virtualenv_path="", # empty — use system Python
project_path="/home/<username>/<app-name>"
)If webapp already exists, skip to Step 4.
Gate: returns webapp with correct .
get_webapp_infosource_directorypython
create_webapp(
domain="<username>.pythonanywhere.com",
python_version="3.12",
virtualenv_path="", # 留空——使用系统Python
project_path="/home/<username>/<app-name>"
)如果Web应用已存在,直接跳至步骤4。
检查点: 返回的Web应用信息中正确。
get_webapp_infosource_directoryStep 4 — Point WSGI to our file
步骤4 — 将WSGI指向我们的文件
python
patch_webapp(
domain="<username>.pythonanywhere.com",
data={"source_directory": "/home/<username>/<app-name>"}
)Note: PA's WSGI file path is set at creation. If it doesn't match flask_app.py, user must set it in Web tab manually (no API for WSGI path).
Gate: shows correct .
get_webapp_infosource_directorypython
patch_webapp(
domain="<username>.pythonanywhere.com",
data={"source_directory": "/home/<username>/<app-name>"}
)注意:PA的WSGI文件路径在创建Web应用时设置。如果该路径与上传的flask_app.py不匹配,用户必须在Web标签页手动修改(暂无API可修改WSGI路径)。
检查点: 显示的正确。
get_webapp_infosource_directoryStep 5 — Reload
步骤5 — 重载Web应用
python
reload_webapp(domain="<username>.pythonanywhere.com")Gate: returns 200.
curl GET https://<user>.pythonanywhere.com/python
reload_webapp(domain="<username>.pythonanywhere.com")检查点: 返回状态码200。
curl GET https://<user>.pythonanywhere.com/Step 6 — E2E test
步骤6 — 端到端测试
- Homepage: → 200.
curl GET - Upload real file:
bash
curl -s -w "\nHTTP:%{http_code} TIME:%{time_total}" \ --max-time 300 \ -X POST -F "file=@<source-file>" \ "https://<user>.pythonanywhere.com/<endpoint>" \ -o /tmp/pa_result.xlsx - Verify output: correct row count, correct totals vs known-good reference.
Gate: HTTP 200, output validates. If 400/500, read error log:
python
read_file_or_directory("/var/log/<user>.pythonanywhere.com.error.log")Diagnose + fix + reload + retest.
- 首页测试:→ 返回状态码200。
curl GET - 上传真实文件:
bash
curl -s -w "\nHTTP:%{http_code} TIME:%{time_total}" \ --max-time 300 \ -X POST -F "file=@<source-file>" \ "https://<user>.pythonanywhere.com/<endpoint>" \ -o /tmp/pa_result.xlsx - 验证输出:行数正确,总计与已知正确的参考值一致。
检查点: 返回HTTP 200,输出验证通过。如果返回400/500,读取错误日志:
python
read_file_or_directory("/var/log/<user>.pythonanywhere.com.error.log")排查问题并修复 → 重载Web应用 → 重新测试。
Gotchas (learned the hard way)
注意事项(经验总结)
TemporaryDirectoryTemporaryDirectory.__exit__OSError: [Errno 39] Directory not emptytempfile.mkdtemp()shutil.rmtree(ignore_errors=True)finallysend_file(io.BytesIO(result_bytes))Stale . Python serves cached after source changes. Every deploy: + . Symptom: old errors persist in error log.
__pycache__.pycdelete_path(__pycache__)reload_webappsend_filebytesAttributeErrorio.BytesIO()Free tier sleep. 20-40s cold start after idle. Normal.
No virtualenv needed. PA system Python has flask/openpyxl in site-packages. Don't create one — wastes time.
WSGI path. PA sets this at webapp creation and shows it in Web tab. If it doesn't match the uploaded WSGI file, user must manually update in Web tab config (no API).
TemporaryDirectoryTemporaryDirectory.__exit__OSError: [Errno 39] Directory not emptytempfile.mkdtemp()finallyshutil.rmtree(ignore_errors=True)send_file(io.BytesIO(result_bytes))过期的。 源代码修改后,Python仍会加载缓存的文件。每次部署时:执行 + 。症状:错误日志中仍存在旧错误。
__pycache__.pycdelete_path(__pycache__)reload_webappsend_filebytesAttributeErrorio.BytesIO()免费层级休眠机制。 闲置后冷启动需要20-40秒,属于正常现象。
无需虚拟环境。 PA系统Python已在site-packages中预装flask/openpyxl。无需创建虚拟环境——纯属浪费时间。
WSGI路径。 PA在创建Web应用时设置该路径,并在Web标签页显示。如果该路径与上传的WSGI文件不匹配,用户必须在Web标签页配置中手动更新(暂无API支持)。
Deploy update (code change only)
部署更新(仅代码变更)
When code changes but webapp already exists:
- new code
upload_directory delete_path(__pycache__)reload_webapp- E2E test
Skip Steps 2-4 (webapp + WSGI already configured).
当代码变更但Web应用已存在时:
- 上传新代码
upload_directory - 删除缓存
delete_path(__pycache__) - 重载Web应用
reload_webapp - 执行端到端测试
跳过步骤2-4(Web应用和WSGI已配置完成)。