All Products
Search
Document Center

Python handler

Last Updated: Dec 08, 2018

To use Python in Function Compute, you must define a Python function as a handler. Current Python runtime environments support either common handlers or handlers with an HTTP trigger. With the HTTP trigger, HTTP requests can be processed more efficiently. Except for the handlers with an HTTP trigger, all other Python-compiled function handlers are the same.

Currently, Function Compute supports the Python 2.7 (runtime version 2.7) and Python 3.6 (runtime version 3). For more information, see Python runtime.

Contents

This topic describes the common handlers and handlers with an HTTP trigger.

Common handlers

A simple function is defined as follows:

  1. def my_handler(event, context):
  2. return 'hello world'

Function name

  • my_handler: The function name must match the “handler” field provided when a function is created. For example, if handler is specified as main.my_handler, Function Compute obtains the my_handler function defined in main.py.

Parameter event

  • The event parameter is defined when you call a function. In Python 2.7, this parameter is of str type. In Python 3, it is of bytes type. The parameter is an input parameter.
  • You can convert this parameter as needed because it is not defined by the function. For example, if a JSON string is passed in, you can convert the parameter to one that is of the dict type.Example:Defined event:
    1. {
    2. "key": "value"
    3. }
    Function code:
    1. # -*- coding: utf-8 -*-
    2. import json
    3. def my_handler(event, context):
    4. evt = json.loads(event)
    5. return evt['key']
    The value parameter is returned.

Parameter context

  • The context parameter contains information generated when the function is executed, for example, the request ID and temporary AccessKey credentials. You can use the generated information when coding. This parameter is of the FCContext type.
  • The context parameter can be defined as follows:
  1. class Credentials:
  2. def __init__(self, access_key_id, access_key_secret, security_token):
  3. self.access_key_id = access_key_id
  4. self.access_key_secret = access_key_secret
  5. self.security_token = security_token
  6. class ServiceMeta:
  7. def __init__(self, service_name, log_project, log_store):
  8. self.name = service_name
  9. self.log_project = log_project
  10. self.log_store = log_store
  11. self.qualifier = qualifier
  12. self.version_id = version_id
  13. class FunctionMeta:
  14. def __init__(self, name, handler, memory, timeout):
  15. self.name = name
  16. self.handler = handler
  17. self.memory = memory
  18. self.timeout = timeout
  19. class FCContext:
  20. def __init__(self, account_id, request_id, credentials, function_meta, service_meta, region):
  21. self.request_id = request_id
  22. self.credentials = credentials
  23. self.function = function_meta
  24. self.service = service_meta
  25. self.region = region
  26. self.account_id = account_id

In the preceding functions, key parameters include:

  • request_id: indicates the unique ID of this call. You can note down this parameter for troubleshooting if an exception occurs.
  • function: indicates the basic information about this function, including the function name, handler, function memory, and timeout period.
  • credentials: indicates a set of keys that Function Compute obtains from assuming your service role. These keys expire 15 minutes after it is generated. You can use this parameter to access certain services, such as Object Storage Service (OSS). This prevents you from permanently writing your AccessKey credentials in the function code.
  • service: specifies the details of the service that the current function serves. For example, this parameter may include the service name, and the log project and Logstore in Log Service, qualifier and versionId which indicate the service version.
  • region: indicates the region where this function applies, such as cn-shanghai.
  • accountId: indicates the ID of your Alibaba Cloud account.

In the following code, a Security Token Service (STS) token is used to send a file to OSS.

  1. import json
  2. import oss2
  3. def my_handler(event, context):
  4. evt = json.loads(event)
  5. creds = context.credentials
  6. # you must enter the security_token
  7. auth = oss2.StsAuth(creds.access_key_id, creds.access_key_secret, creds.security_token)
  8. bucket = oss2.Bucket(auth, evt['endpoint'], evt['bucket'])
  9. bucket.put_object(evt['objectName'], evt['message'])
  10. return 'success'

Note: You must provide a temporary token for the temporary key so that the key can be used to access OSS.

Handlers with an HTTP trigger

Handlers with an HTTP trigger are different from common handlers. An HTTP trigger supports the following handlers:

  • Method 1. User provides the function. Function Compute calls the function to process the request and send back the response.

    1. HELLO_WORLD = b"Hello world!\n"
    2. def handler(environ, start_response):
    3. context = environ['fc.context']
    4. request_uri = environ['fc.request_uri']
    5. for k, v in environ.items():
    6. if k.startswith("HTTP_"):
    7. # process custom request headers
    8. pass
    9. # get request_body
    10. try:
    11. request_body_size = int(environ.get('CONTENT_LENGTH', 0))
    12. except (ValueError):
    13. request_body_size = 0
    14. request_body = environ['wsgi.input'].read(request_body_size)
    15. # get request_method
    16. request_method = environ['REQUEST_METHOD']
    17. # get path info
    18. path_info = environ['PATH_INFO']
    19. # get server_protocol
    20. server_protocol = environ['SERVER_PROTOCOL']
    21. # get content_type
    22. try:
    23. content_type = environ['CONTENT_TYPE']
    24. except (KeyError):
    25. content_type = " "
    26. # get query_string
    27. try:
    28. query_string = environ['QUERY_STRING']
    29. except (KeyError):
    30. query_string = " "
    31. print 'request_body: {}'.format(request_body)
    32. print 'method: {}\n path: {}\n query_string: {}\n server_protocol: {}\n'.format(request_method, path_info, query_string, server_protocol)
    33. # do something here
    34. status = '200 OK'
    35. response_headers = [('Content-type', 'text/plain')]
    36. start_response(status, response_headers)
    37. # return value must be iterable
    38. return [HELLO_WORLD]
  • Method 2. User provides the callable class object. Function Compute calls the object to process the request and send back the response.

    1. HELLO_WORLD = b"Hello world!\n"
    2. class AppClass:
    3. """Produce the same output, but using a class
    4. """
    5. def __init__(self, environ, start_response):
    6. self.environ = environ
    7. self.start = start_response
    8. def __iter__(self):
    9. status = '200 OK'
    10. response_headers = [('Content-type', 'text/plain')]
    11. self.start(status, response_headers)
    12. yield HELLO_WORLD
    13. def handler(environ, start_response):
    14. return AppClass(environ, start_response)

Function signatures in Python runtime environments comply with the Python Web Server Gateway Interface (WSGI) convention.

Input parameters

  • environ: This parameter represents a Python dictionary that stores all client-related information. For more information, see Parameter environ. Two user-defined keys, fc.context and fc.request_uri, are added to Function Compute.

    • fc.context: functions as the context parameter of common handlers.

    • fc.request_uri: indicates the URL of the request. This parameter is a string.

    Note: The HTTP_Variables field of environ contains the request header. For example, if the request header is 'x-Custom-key':'value', the environ parameter will be environ['HTTP_X_CUSTOM_KEY']='value'. According to WSGI, the key in the request header is processed as follows: key = "HTTP_" + k.upper().replace("-","_").

  • start_response: The start_response callable is provided in runtime environments of Function Compute. It has two required positional parameters and one optional parameter. For more information, see the-start-response-callable. In the following example, the three parameters are named status, response_headers, and exc_info. You can use other names as needed.

    1. # Provided by Function Compute runtime.
    2. # status: a string such as '200 OK' or '403 FORBIDDEN'
    3. # return: must be a write(body_data) callable
    4. def start_response(status, response_headers, exc_info=None):
    5. ...
    • status: indicates the HTTP response status. This parameter is a string.
    • response_headers: represents the HTTP request headers. It is a list that contains a tuple in the (header_name, header_value) format.

    • exc_info (optional): indicates the information that the server needs to return to the client.

    After the application object completes executing the service logic based on the environ parameter, the application object must return the result to the server. An HTTP response must contain the status, headers, and body parameters. Therefore, before the application returns the value of body, you must call the start_response() function to return the value of status and headers to the server. In this way, the server knows that the application is starting to return the value of body.

Deploy WSGI-based web frameworks for Function Compute

The preceding Method2 example shows that you can run projects that are built on WSGI-based web frameworks using Flask and Django in Python runtime environments of Function Compute. The following uses Flask as an example:

  1. from flask import Flask
  2. from flask import request
  3. from flask import make_response
  4. app = Flask(__name__)
  5. @app.route('/', methods=['GET', 'POST'])
  6. def home():
  7. resp = make_response('<h1>Home</h1>', 200)
  8. return resp
  9. @app.route('/signin', methods=['GET'])
  10. def signin_form():
  11. # service_name,function_name in action url need to be replaced
  12. html = '''<form action="/2016-08-15/proxy/service_name/func_name/signin" method="post">
  13. <p><input name="username"></p>
  14. <p><input name="password" type="password"></p>
  15. <p><button type="submit">Sign In</button></p>
  16. </form>'''
  17. resp = make_response(html, 200)
  18. return resp
  19. @app.route('/signin', methods=['POST'])
  20. def signin():
  21. if request.form['username'] == 'admin' and request.form['password'] == 'password':
  22. html = '<h3>Hello, admin!</h3>'
  23. else:
  24. html = '<h3>Bad username or password.</h3>'
  25. resp = make_response(html, 200)
  26. return resp
  27. @app.route('/signin2', methods=['GET'])
  28. def signin2():
  29. if request.args.get('username') == 'admin' and request.args.get('password') == 'password':
  30. html = '<h3>Hello2, admin!</h3>'
  31. else:
  32. html = '<h3>Bad username or password.</h3>'
  33. resp = make_response(html, 200)
  34. return resp
  35. def handler(environ, start_response):
  36. # do something here
  37. return app(environ, start_response)