Getting Started with Python on Heroku
Last updated 12 August 2015
Table of Contents
See our new Getting Started with Python tutorial for an improved getting started experience.
This quickstart will get you going with a Python application that uses the Flask web framework, deployed to Heroku. For Django apps, please see the Getting Started with Django on Heroku. For general information on how to develop and architect apps for use on Heroku, see Architecting Applications for Heroku.
If you have questions about Python on Heroku, consider discussing it in the Python on Heroku forums. Both Heroku and community-based Python experts are available.
- Basic Python knowledge.
- Installed Python and Virtualenv in a unix-style environment. See this guide for guidance.
- Your application must use Pip to resolve dependencies.
- A Heroku user account. Signup is free and instant.
Local workstation setup
First, install the Heroku Toolbelt on your local workstation.
This ensures that you have access to the Heroku command-line client, which includes the
heroku local command.
Once installed, you can use the
heroku command from your command shell. Log in using the email address and password you used when creating your Heroku account:
$ heroku login Enter your Heroku credentials. Email: email@example.com Password: Could not find an existing public key. Would you like to generate one? [Yn] Generating new SSH public key. Uploading ssh public key /Users/kenneth/.ssh/id_rsa.pub
Press enter at the prompt to upload your existing
ssh key or create a new one, used for pushing code later on.
Start Flask app inside a Virtualenv
First, we’ll create an empty top-level directory for our project:
$ mkdir helloflask $ cd helloflask
Next, we’ll create a Python Virtualenv (v1.0+):
Make sure you're using the latest virtualenv release. If you're using a version that comes with Ubuntu, you may need to add the
$ virtualenv venv New python executable in venv/bin/python Installing setuptools, pip...done.
To use our new virtualenv, we need to activate it. (You must source the virtualenv environment for each terminal session where you wish to run your app.)
$ source venv/bin/activate
Next, install our application’s dependencies with pip. In this case, we will be installing Flask, the web framework, and Gunicorn, the web server.
$ pip install Flask gunicorn Downloading/unpacking Flask Downloading Flask-0.9.tar.gz (481kB): 481kB downloaded Downloading/unpacking gunicorn Downloading gunicorn-0.17.2.tar.gz (360kB): 360kB downloaded Running setup.py egg_info for package gunicorn Downloading/unpacking Werkzeug>=0.7 (from Flask) Downloading Werkzeug-0.8.3.tar.gz (1.1MB): 1.1MB downloaded Downloading/unpacking Jinja2>=2.4 (from Flask) Downloading Jinja2-2.6.tar.gz (389kB): 389kB downloaded Installing collected packages: Flask, gunicorn, Werkzeug, Jinja2 Running setup.py install for Flask Running setup.py install for gunicorn Running setup.py install for Werkzeug Running setup.py install for Jinja2 Successfully installed Flask gunicorn Werkzeug Jinja2
Now that we have a clean Flask environment to work in, we’ll create our simple application,
import os from flask import Flask app = Flask(__name__) @app.route('/') def hello(): return 'Hello World!'
Declare process types with Procfile
Use a Procfile, a text file in the root directory of your application, to explicitly declare what command should be executed to start a web dyno. In this case, you need to execute Gunicorn with a few arguments.
Procfile for our new app. It should be called
Procfile and live at the root directory of our project:
web: gunicorn hello:app --log-file=-
You can now start the processes in your Procfile locally using
heroku local (installed as part of the Toolbelt):
$ heroku local 2013-04-03 16:11:22  [INFO] Starting gunicorn 0.14.6 2013-04-03 16:11:22  [INFO] Listening at: http://127.0.0.1:5000 (8469)
Make sure things are working properly with
curl or a web browser at http://localhost:5000/, then Ctrl-C to exit.
Specify dependencies with Pip
Heroku recognizes Python applications by the existence of a
requirements.txt file in the root of a repository. This simple format is used by most Python projects to specify the external Python modules the application requires.
Pip has a nice command (
pip freeze) that will generate this file for us:
$ pip freeze > requirements.txt
Flask==0.9 Jinja2==2.6 Werkzeug==0.8.3 gunicorn==0.17.2
Pip can also be used for advanced dependency management. See Python Dependencies via Pip to learn more.
Store your app in Git
Now that we’ve written and tested our application, we need to store the project in a Git repository.
Since our current directory contains a lof of extra files, we’ll want to configure our repository to ignore these files with a
Next, we’ll create a new git repository and save our changes.
$ git init $ git add . $ git commit -m "init"
Deploy your application to Heroku
The next step is to push the application’s repository to Heroku. First, we have to get a place to push to from Heroku. We can do this with the
heroku create command:
$ heroku create Creating stark-window-524... done, stack is cedar-14 http://stark-window-524.herokuapp.com/ | firstname.lastname@example.org:stark-window-524.git Git remote heroku added
This automatically added the Heroku remote for our app (
email@example.com:stark-window-524.git) to our repository. Now we can do a simple
git push to deploy our application:
$ git push heroku master Counting objects: 10, done. Delta compression using up to 8 threads. Compressing objects: 100% (8/8), done. Writing objects: 100% (10/10), 3.59 KiB, done. Total 10 (delta 0), reused 0 (delta 0) -----> Heroku receiving push -----> Python app detected -----> No runtime.txt provided; assuming python-2.7.6. -----> Preparing Python runtime (python-2.7.6) -----> Installing Distribute (0.6.36) -----> Installing Pip (1.3.1) -----> Installing dependencies using Pip (1.3.1) ... Successfully installed Flask Werkzeug Jinja2 gunicorn Cleaning up... -----> Discovering process types Procfile declares types -> web -----> Compiled slug size is 3.5MB -----> Launching... done, v2 http://stark-window-524.herokuapp.com deployed to Heroku To firstname.lastname@example.org:stark-window-524.git * [new branch] master -> master
Visit your application
You’ve deployed your code to Heroku, and specified the process types in a
Procfile. You can now instruct Heroku to execute a process type. Heroku does this by running the associated command in a dyno - a lightweight container which is the basic unit of composition on Heroku.
Let’s ensure we have one dyno running the
web process type:
$ heroku ps:scale web=1 Scaling web processes... done, now running 1
You can check the state of the app’s dynos. The
heroku ps command lists the running dynos of your application:
$ heroku ps === web: `gunicorn hello:app` web.1: up for 5s
Here, one dyno is running.
We can now visit the app in our browser with
$ heroku open Opening stark-window-524... done
Dyno sleeping and scaling
By default, your app is deployed on a free dyno. Free dynos will sleep after a half hour of inactivity and they can be active (receiving traffic) for no more than 18 hours a day before going to sleep. If a free dyno is sleeping, and it hasn’t exceeded the 18 hours, any web request will wake it. This causes a delay of a few seconds for the first request upon waking. Subsequent requests will perform normally.
To avoid dyno sleeping, you can upgrade to a hobby or professional dyno type as described in the Dyno Types article. For example, if you migrate your app to a professional dyno, you can easily scale it by running a command telling Heroku to execute a specific number of dynos, each running your web process type.
View the logs
Heroku treats logs as streams of time-ordered events aggregated from the output streams of all the dynos running the components of your application. Heroku’s Logplex provides a single channel for all of these events.
View information about your running app using one of the logging commands,
$ heroku logs 2011-08-20T16:33:39+00:00 heroku[slugc]: Slug compilation started 2011-08-20T16:34:07+00:00 heroku[api]: Config add PYTHONUNBUFFERED by email@example.com 2011-08-20T16:34:07+00:00 heroku[api]: Release v1 created by firstname.lastname@example.org 2011-08-20T16:34:07+00:00 heroku[api]: Deploy 67b7e54 by email@example.com 2011-08-20T16:34:07+00:00 heroku[api]: Release v2 created by firstname.lastname@example.org 2011-08-20T16:34:08+00:00 heroku[web.1]: State changed from created to starting 2011-08-20T16:34:08+00:00 heroku[slugc]: Slug compilation finished 2011-08-20T16:34:10+00:00 heroku[web.1]: Starting process with command `gunicorn hello:app` 2011-08-20T16:34:10+00:00 app[web.1]: * Running on http://0.0.0.0:17658/ 2011-08-20T16:34:11+00:00 heroku[web.1]: State changed from starting to up
Heroku allows you to run commands in a one-off dyno - scripts and applications that only need to be executed when needed - using the
heroku run command. Use this to launch a Python shell attached to your local terminal for experimenting in your app’s environment:
$ heroku run python Running python attached to terminal... up, run.1 Python 2.7.6 (default, Jan 16 2014, 02:39:37) [GCC 4.4.3] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>>
From here you can
import some of your application modules.
Running a worker
Procfile format lets you run any number of different process types. For example, let’s say you wanted a worker process to complement your web process:
web: gunicorn hello:app --log-file - worker: python worker.py
Running more than one dyno for an extended period may incur charges to your account. Read more about dyno-hour costs.
Push this change to Heroku, then launch a worker:
$ heroku ps:scale worker=1 Scaling worker processes... done, now running 1
heroku ps to see that your worker comes up, and
heroku logs to see your worker doing its work.
Now that you’ve deployed your first Python application to Heroku, it’s time to take the next step! If if you’d like to learn more about Heroku, these articles are a great place to start.