Skip to content

Deploying to PythonAnywhere

PythonAnywhere is beginner-friendly for Flask hosting.

  • Create a web app (Flask)
  • Create a virtualenv on PythonAnywhere
  • Install requirements
  • Configure the WSGI file to point to your Flask app

PythonAnywhere provides a WSGI config file where you import your app:

python
from myapp import create_app
 
application = create_app()

Note: PythonAnywhere uses application as the variable name.

  • wrong virtualenv selected
  • missing packages
  • incorrect module import paths
  • static files not configured

PythonAnywhere is great for:

  • learning deployments
  • small projects

For advanced ops (containers, autoscaling), use a cloud VM or container platform.

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:

diagram Diagram mermaid
/var/www/USERNAME_pythonanywhere_com_wsgi.py
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 app alone leaves it undefined, and the error is an import failure rather than anything mentioning WSGI.
  • sys.path must include your project, because the WSGI file lives in /var/www/ and your code does not.

The same local check applies as anywhere else:

verify.py
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”
PythonAnywherecontainer platform
how your app startstheir server imports ityou supply a start command
the serverprovided, you do not run gunicornyou run gunicorn yourself
static filesmapped in the dashboard, served directlyusually your own concern
filesystempersistentephemeral
deploypull or upload, then reloadpush, 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.

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.

Map the URL prefix to the directory in the dashboard:

static mapping
URL:       /static/
Directory: /home/USERNAME/mysite/static

Their server then serves those files directly, without touching your application — the same division of labour as Nginx in front of gunicorn.

sketch Two hosting models, same application p5.js
One platform imports your WSGI callable; the other runs a command you supply. The application object is identical either way.
pch.quizTag pch.quizDefaultTitle
  1. In a PythonAnywhere WSGI file, why is the import written as from app import app as application?

    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.

  2. Your code change appears to have no effect on PythonAnywhere. What is the most likely cause?

    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.

  3. How does PythonAnywhere's filesystem differ from a typical container platform?

    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.coffeeCta

pch.feedbackHeading

pch.feedbackSubheading