Python

By default, Stackato uses the built-in Python Buildpack to deploy Python applications. To deploy applications using this buildpack, your application will need the following in the root directory of the application:

  • a list of module requirements in a stackato.yml, requirements.txt (pip), or requirements.pypm (pypm) file.

  • a Procfile specifying the command to run the application server. For example, the example-python-django Stackato sample has the following simple Procfile:

    web: gunicorn stackato.wsgi -b 0.0.0.0:$PORT
    

This buildpack uses Python 2.7 by default. To specify Python 3.3, create a runtime.txt file setting the version (i.e. python-3.3) and use the $PYTHON_VERSION environment variable in the Procfile web: command. For example:

web: python$PYTHON_VERSION app.py

See also: https://github.com/ActiveState/stackato-buildpack-python

Python with the Legacy Buildpack

If your Python application has configuration for running on Stackato 2.10 or earlier, you can deploy it using the Legacy Buildpack, which provides an updated version of the old Python framework.

With the Legacy Buildpack, applications are run with uWSGI. Applications are started from a top-level script called wsgi.py defining a global application variable containing the WSGI application object. For a minimal sample application, see wsgi-helloworld.

You may add additional arguments to uWSGI in your stackato.yml, eg:

processes:
  web: $STACKATO_UWSGI --mount foo=app.py --import module

It is possible to serve static files with uWSGI.

Application URL

Some applications require the user to specify the APP_URL. Below is an example on how to obtain the correct urls:

import json
vcap_app = json.loads(os.environ['VCAP_APPLICATION'])
APP_URL = 'http://' + vcap_app['uris'][0]

Database Services

Some minor edits are required to make your application work with a database. Python database configurations are located inside settings.py.

DATABASE_URL

Authentication details for your configured database services can be found in the os.environ variable, under DATABASE_URL. Here is an example of getting the correct credentials.

import urlparse
DATABASES = {}
if 'DATABASE_URL' in os.environ:
    url = urlparse.urlparse(os.environ['DATABASE_URL'])
    DATABASES['default'] = {
        'NAME': url.path[1:],
        'USER': url.username,
        'PASSWORD': url.password,
        'HOST': url.hostname,
        'PORT': url.port,
        }
    if url.scheme == 'postgres':
        DATABASES['default']['ENGINE'] = 'django.db.backends.postgresql_psycopg2'
    elif url.scheme == 'mysql':
        DATABASES['default']['ENGINE'] = 'django.db.backends.mysql'
else:
    DATABASES['default'] = {
        'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
        'NAME': 'dev.db',                      # Or path to database file if using sqlite3.
        'USER': '',                      # Not used with sqlite3.
        'PASSWORD': '',                  # Not used with sqlite3.
        'HOST': '',                      # Set to empty string for localhost. Not used with sqlite3.
        'PORT': '',                      # Set to empty string for default. Not used with sqlite3.
        }

VCAP_SERVICES

import json
vcap_services = json.loads(os.environ['VCAP_SERVICES'])
srv = vcap_services['mysql'][0]
cred = srv['credentials']
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': cred['name'],
        'USER': cred['user'],
        'PASSWORD': cred['password'],
        'HOST': cred['hostname'],
        'PORT': cred['port'],
    }
}

Worker Applications

Non-HTTP apps that run as a Stackato application under the control of the Health Manager.

To deploy worker applications, you need to use the command key and set the proceses: web key to Null ("~").

Example

name: python-app
framework:
  type: python
  runtime: python27
command: python worker.py
processes:
  web: ~

Serving Static Files with uWSGI

It is possible to serve static files with uWSGI using processes: web: in the stackato.yml file to specify folders that will be served statically and not by the app.

To make a single folder serve statically, use --check-static:

processes:
    web: $STACKATO_UWSGI --check-static $HOME/<folder>

To specify multiple folders with static files that do not share a common root, use --static-map:

processes:
    web: $STACKATO_UWSGI --static-map /foo=$HOME/static --static-map /bar=$HOME/sub

In this case /foo/index.html would serve $HOME/static/index.html, and /bar/index.html would serve $HOME/sub/index.html. If the file doesn't exist, then uWSGI will forward the request to the app.

Note

Serving static files via uWSGI is only available for Perl and Python frameworks.

Using a custom web server

To use a different web server, instead of uWSGI, specify its startup command in stackato.yml. Here's a sample stackato.yml used to deploy a Django 1.4 application named "dj14" using gunicorn:

name: dj14

framework:
  type: python

processes:
  web: gunicorn -b 0.0.0.0:$PORT dj14.wsgi

requirements:
  pypm: [gunicorn]
  pip: ["http://www.djangoproject.com/download/1.4-beta-1/tarball/#egg=django-1.4b1"]

The custom web server must bind to IP address 0.0.0.0 and port $PORT. The same trick can be used to serve non-WSGI applications (such as Tornado). See the bottle-py3 example sample for an example.

Installing Python Packages

Note

To install packages from custom repository/mirror. Use the PIP_OPTS or PYPM_OPTS environment variables.

Application dependencies such as web frameworks or modules from PyPI can be installed using PyPM and/or pip.

PyPM

Definition PyPM

To install packages during application deployment with PyPM, add the requirements to stackato.yml:

requirements:
  pypm:
    - tornado
    - pymongo

See the stackato.yml of tornado-chat-mongo sample app for an example.

Alternatively, you can list the modules in a top-level requirements-pypm.txt file. The format is similar, if not same, as pip requirements files and accepts version specification. The name of this file can be overriden by setting the PYPM_REQUIREMENTS_FILE environment variable.

pip

Definition pip

In addition - or as alternative - to PyPM, your application can also make use of pip to install certain dependencies. The above tornado-chat-mongo sample installs "pycurl" using pip:

requirements:
  pypm:
    - tornado
    - pymongo
  pip:
    - pycurl

If your application already contains a requirements.txt file, that will be automatically used to install dependencies; no need to specify them manually in stackato.yml. The name of this file can be overriden by setting the PIP_REQUIREMENTS_FILE environment variable.

Note

A bug in pip may prevent the log file from being accessed by stackato logs.

PyPy Support

Here is an example of pushing an app using PyPy.

First, clone the https://github.com/Stackato-Apps/werkzeug-debugger repository.

Then add a buildpack: entry to the stackato.yml file:

buildpack: git://github.com/ActiveState/heroku-buildpack-pypy.git

Finally, push the app to Stackato:

$ stackato push -n

Other Python Frameworks

Examples of deploying other frameworks are included in the GitHub samples repo: