Deploying to PythonAnywhere
PythonAnywhere is beginner-friendly for Flask hosting.
Typical steps (conceptual)
Section titled “Typical steps (conceptual)”- Create a web app (Flask)
- Create a virtualenv on PythonAnywhere
- Install requirements
- Configure the WSGI file to point to your Flask app
WSGI file idea
Section titled “WSGI file idea”PythonAnywhere provides a WSGI config file where you import your app:
from myapp import create_app
application = create_app()Note: PythonAnywhere uses application as the variable name.
Common pitfalls
Section titled “Common pitfalls”- wrong virtualenv selected
- missing packages
- incorrect module import paths
- static files not configured
Good fit
Section titled “Good fit”PythonAnywhere is great for:
- learning deployments
- small projects
For advanced ops (containers, autoscaling), use a cloud VM or container platform.
A different model from most hosts
Section titled “A different model from most hosts”PythonAnywhere does not run your process from a start command. It hosts a WSGI file that imports your application object, and its own web server calls it:
flowchart TD W["/var/www/USERNAME_pythonanywhere_com_wsgi.py"] --> P["adds your project to sys.path"] P --> I["from app import app as application"] I --> S["PythonAnywhere's server calls it"] S --> R["your views run"] V["a virtualenv you create"] --> S E["environment variables set in that WSGI file
or loaded from a file outside the repo"] --> I
The WSGI file is the whole integration
Section titled “The WSGI file is the whole integration”import sys
import os
path = "/home/USERNAME/mysite"
if path not in sys.path:
sys.path.insert(0, path)
os.environ["SECRET_KEY"] = "..." # or load from a file outside the repo
os.environ["DATABASE_URL"] = "..."
from app import app as application # the name MUST be `application`Two details cause most failures:
- The variable must be called
application. That is the WSGI convention their server looks for.from app import appalone leaves it undefined, and the error is an import failure rather than anything mentioning WSGI. sys.pathmust include your project, because the WSGI file lives in/var/www/and your code does not.
The same local check applies as anywhere else:
import importlib
application = getattr(importlib.import_module("app"), "app")
assert callable(application)Measured on the demo app: resolved to a Flask object and served 200. If this fails
locally it will fail there, for the same reason, with a worse error message.
What is different from a container platform
Section titled “What is different from a container platform”| PythonAnywhere | container platform | |
|---|---|---|
| how your app starts | their server imports it | you supply a start command |
| the server | provided, you do not run gunicorn | you run gunicorn yourself |
| static files | mapped in the dashboard, served directly | usually your own concern |
| filesystem | persistent | ephemeral |
| deploy | pull or upload, then reload | push, rebuild, replace |
The persistent filesystem is the genuinely notable difference: a SQLite database in your home directory survives reloads, which makes this a reasonable host for a small project that would need a managed database elsewhere. It is also a single machine, so that convenience does not scale horizontally.
The reload step
Section titled “The reload step”Code changes take effect only after Reload in the Web tab — there is no watcher. An edit that appears to have no effect is almost always an unreloaded app, and it is worth checking that before debugging anything else.
Static files
Section titled “Static files”Map the URL prefix to the directory in the dashboard:
URL: /static/
Directory: /home/USERNAME/mysite/staticTheir server then serves those files directly, without touching your application — the same division of labour as Nginx in front of gunicorn.
See it move
Section titled “See it move”Check yourself
Section titled “Check yourself”-
In a PythonAnywhere WSGI file, why is the import written as from app import app as application?
Importing it under any other name leaves application undefined, and the failure looks like an ordinary import error rather than anything about WSGI.
pch.quizShowAnswer
B — their server looks for a WSGI callable named application, which is the WSGI convention — Importing it under any other name leaves application undefined, and the failure looks like an ordinary import error rather than anything about WSGI.
-
Your code change appears to have no effect on PythonAnywhere. What is the most likely cause?
Reload is an explicit step. Checking it first saves debugging a problem that does not exist.
pch.quizShowAnswer
B — the app was not reloaded from the Web tab; there is no file watcher — Reload is an explicit step. Checking it first saves debugging a problem that does not exist.
-
How does PythonAnywhere's filesystem differ from a typical container platform?
That makes it reasonable for a small project that would need a managed database on an ephemeral host, at the cost of not scaling horizontally.
pch.quizShowAnswer
B — it is persistent, so a SQLite file survives reloads — convenient, but tied to a single machine — That makes it reasonable for a small project that would need a managed database on an ephemeral host, at the cost of not scaling horizontally.
pch.coffeeTagline
pch.coffeeCtapch.feedbackHeading
pch.feedbackSubheading