The Python Runtime

Overview

The Python runtime is the software stack responsible for installing your application code and its dependencies and running your application. The standard runtime is declared in app.yaml as runtime: python:

runtime: python
env: flex

Runtimes in the flexible environment are built using Docker. The Python runtime is based on Debian Jessie. The source code for the Python runtime is publicly available on GitHub.

Interpreter

The default interpreter is Python 2.7.9. You can specify whether to use Python 2 or Python 3 in your application's app.yaml with the runtime_config setting:

runtime: python
env: flex

runtime_config:
    python_version: 3

The following interpreter versions are supported:

  • Python 2.7.9 as specified by 2.
  • Python 3.5.2 as specified by 3.

Dependencies

The runtime looks for a requirements.txt file in your application's source directory and uses pip to install any dependencies before starting your application. For more information on declaring and managing packages, see Using Python Libraries

Using C libraries with Python

To enable the use of Python packages that require C extensions, the headers for the current Python version and the following Debian packages are pre-installed on the system.

These packages allow the installation of most popular Python libraries. If your application requires additional operating-system level dependencies, you will need to use a custom runtime based on this runtime to install the appropriate packages.

Application startup

The runtime starts your application using the entrypoint defined in app.yaml. The entrypoint should start a process that responds to HTTP requests on the port defined by the environment variable PORT.

Most web applications use a WSGI server such as Gunicorn, uWSGI or Waitress.

Before you can use one of these servers, you must add them as a dependency in your application's requirements.txt. The runtime ensures that all dependences are installed before your entrypoint is called.

Flask==0.10.1
gunicorn==19.3.0

An example entrypoint using gunicorn for a Flask application:

entrypoint: gunicorn -b :$PORT main:app

An example entrypoint using gunicorn for a Django application:

entrypoint: gunicorn -b :$PORT mydjangoapp:wsgi

Gunicorn is the recommended WSGI server, but it's completely possible to use any other WSGI server. For example, here is an entrypoint that uses uWSGI with Flask:

entrypoint: uwsgi --http :$PORT --wsgi-file main.py --callable app

For applications that can handle requests without a WSGI server, you can just execute a python script:

entrypoint: python main.py

The basic entrypoint examples shown above are intended to be starting points and may work for your web applications, however, most applications will need to further configure the WSGI server. Instead of specifying all of the settings on the entrypoint, create a gunicorn.conf.py file and specify it in your entrypoint:

entrypoint: gunicorn -c gunicorn.conf.py -b :$PORT

You can read about all of Gunicorn's configuration values in its documentation.

Worker class

Gunicorn uses workers to handle requests. By default, Gunicorn uses sync workers. This worker class is compatible with all web applications, but each worker can only handle one request at a time. This can often cause your instances to be underutilized and increase latency in applications under high load.

Web applications that are mostly I/O bound can see a performance improvement by using a different worker class such as gevent workers. You can specify the worker class for your application in gunicorn.config.py:

worker_class = 'gevent'

Some worker classes require additional dependencies, for example, the gevent worker requires gevent. These dependencies will need to be declared in your requirements.txt.

HTTPS and forwarding proxies

App Engine terminates the HTTPS connection at the load balancer and forwards the request to your application. Most applications do not need to know if the request was sent over HTTPS or not, but applications that do need this information should configure Gunicorn to trust the App Engine proxy:

forwarded_allow_ips = '*'
secure_scheme_headers = {'X-APPENGINE-HTTPS': 'on'}

Gunicorn will now ensure that the wsgi.url_scheme to 'https', which most web frameworks will use as indication of the request is secure. If your WSGI server or framework doesn't support this, just check the value of the X-AppEngine-Https header manually.

Some applications also need to ascertain the user's IP address. This is available in the X-Appengine-User-Ip header as well as the standard X-Forwarded-For header.

Extending the runtime

The standard python runtime can be used to create a custom runtime. Custom runtimes are configured via Dockerfiles. You can generate a Dockerfile based on the standard Python runtime using gen-config:

gcloud beta app gen-config --custom

You can then customize the Dockerfile and .dockerignore as desired. Finally, you will need to specify runtime: custom instead of runtime: python in app.yaml. See Customizing the Python Runtime for more information.

Environment variables

The following environment variables are set by the runtime environment:

Environment Variable Description
GAE_INSTANCE The name of the current instance.
GAE_MEMORY_MB The amount of memory available to the application process.
GAE_SERVICE The service name specified in your application's app.yaml file, or if no service name is specified, it is set to default.
GAE_VERSION The version label of the current application.
GCLOUD_PROJECT The Project ID associated with your application, which is visible in the Google Cloud Platform Console
PORT The port that will receive HTTP requests.

You can set additional environment variables with app.yaml.

Metadata server

Each instance of your application can use the Compute Engine metadata server to query information about the instance, including its host name, external IP address, instance ID, custom metadata, and service account information. App Engine does not allow you to set custom metadata for each instance, but you can set project-wide custom metadata and read it from your App Engine and Compute Engine instances.

This example function uses the metadata server to get the external IP address of the instance:

METADATA_NETWORK_INTERFACE_URL = \
    ('http://metadata/computeMetadata/v1/instance/network-interfaces/0/'
     'access-configs/0/external-ip')


def get_external_ip():
    """Gets the instance's external IP address from the Compute Engine metadata
    server. If the metadata server is unavailable, it assumes that the
    application is running locally.
    """
    try:
        r = requests.get(
            METADATA_NETWORK_INTERFACE_URL,
            headers={'Metadata-Flavor': 'Google'},
            timeout=2)
        return r.text
    except requests.RequestException:
        logging.info('Metadata server could not be reached, assuming local.')
        return 'localhost'

Send feedback about...

App Engine flexible environment for Python docs