All Products
Search
Document Center

Python

Last Updated: Aug 21, 2019

Function Compute currently supports the following Python runtime environments:

  • Python 2.7 with runtime version 2.7
  • Python 3.6 with runtime version 3

This topic introduces the following features of Python runtime environments:

Use the logging module

You can specify a Logstore when you create a service. The Logstore records the data that the function outputs to stdout. You can store the data to a log file by using the following two methods:

  1. Directly use print: This outputs the original information to logs.

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

    The preceding code outputs the following log content:

    1. message:hello world
  2. Use the logging module: This records the information such as the time, request ID, and log level in each log entry.

    1. import logging
    2. def my_handler(event, context):
    3. logger = logging.getLogger()
    4. logger.info('hello world')
    5. return 'done'

    The preceding code outputs the following log content:

    1. message:2017-07-05T05:13:35.920Z a72df088-f738-cee3-e0fe-323ad89118e5 [INFO] hello world

We recommend that you use the logging module to print logs. With this method, you can retrieve requestIds from log entries. The request IDs facilitate your location of the logs for errors.

Use built-in modules

In addition to the standard Python modules, the Python runtime environments for Function Compute provide other modules for your reference. Currently, the following modules are supported.

Module Description Link
oss2 2.6.0 OSS SDK https://github.com/aliyun/aliyun-oss-python-sdk
tablestore 4.6.0 Table Store SDK https://github.com/aliyun/aliyun-tablestore-python-sdk
aliyun-fc2 2.1.0 Function Compute SDK https://github.com/aliyun/fc-python-sdk
aliyun-python-sdk-ecs 4.10.1 ECS SDK https://github.com/aliyun/aliyun-openapi-python-sdk/tree/master/aliyun-python-sdk-ecs
aliyun-python-sdk-vpc 3.0.2 VPC SDK https://github.com/aliyun/aliyun-openapi-python-sdk/tree/master/aliyun-python-sdk-vpc
aliyun-python-sdk-rds 2.1.4 ApsaraDB for RDS SDK https://github.com/aliyun/aliyun-openapi-python-sdk/tree/master/aliyun-python-sdk-rds
aliyun-python-sdk-kms 2.5.0 Key Management Service SDK https://github.com/aliyun/aliyun-openapi-python-sdk/tree/master/aliyun-python-sdk-kms
pydatahub 2.11.2 DataHub SDK https://github.com/aliyun/aliyun-datahub-sdk-python
aliyun-mns 1.1.5 MNS SDK https://github.com/gikoluo/aliyun-mns
aliyun-python-sdk-cdn 2.6.2 CDN SDK https://github.com/aliyun/aliyun-openapi-python-sdk/tree/master/aliyun-python-sdk-cdn
aliyun-python-sdk-ram 3.0.0 RAM SDK https://github.com/aliyun/aliyun-openapi-python-sdk/tree/master/aliyun-python-sdk-ram
aliyun-python-sdk-sts 3.0.0 STS SDK https://github.com/aliyun/aliyun-openapi-python-sdk/tree/master/aliyun-python-sdk-sts
aliyun-log-python-sdk 0.6.38 Log Service SDK https://github.com/aliyun/aliyun-log-python-sdk
wand 0.4.4 Wand http://docs.wand-py.org/en/0.4.4/
opencv 3.3.0.10 OpenCV http://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_setup/py_intro/py_intro.html
numpy 1.13.3 NumPy http://www.numpy.org/
scipy 1.0.0 SciPy https://www.scipy.org/
matplotlib 2.0.2 Matplotlib https://matplotlib.org/
scrapy 1.4.0 Scrapy https://scrapy.org/
Note: If you use functions of the built-in version aliyun-python-sdk-iot 6.1.0, use the latest version of aliyun-python-sdk-iot as a third-party package as soon as possible.

For example, the function that uses Wand to flip an image is as follows:

  1. from wand.image import Image
  2. def my_handler(event, context):
  3. with Image(blob=event) as img:
  4. print img.size
  5. with img.clone() as i:
  6. i.rotate(180)
  7. return i.make_blob()

Note: The preceding function directly uses event as the binary data of the image, and directly returns the generated image as the binary data.

Note: For other small demos that third-party libraries use, see fc-python-demo.

Use custom modules

If you need to use a custom module, package the module and the code together. The following steps describe how to use Fun to add a PyMySQL module to access MySQL:

  1. Create a folder to store code and dependent modules:

    1. mkdir /tmp/code
  2. Create a new code file, such as /tmp/code/index.py, and use the pymysql module in the code:

    1. import pymysql.cursors
    2. connection = None
    3. # my_initializer: initializer function
    4. def my_initializer(context):
    5. global connection
    6. connection = pymysql.connect(host='localhost',
    7. user='user',
    8. password='passwd',
    9. db='db',
    10. charset='utf8mb4',
    11. cursorclass=pymysql.cursors.DictCursor)
    12. def my_handler(event, context):
    13. global connection
    14. with connection.cursor() as cursor:
    15. # Read a single record
    16. sql = "SELECT count(*) FROM `users`"
    17. cursor.execute(sql)
    18. result = cursor.fetchone()
    19. print(result)
    20. return result
    • Why is the database connection operation in the initializer?

      The initializer runs only once within the lifecycle of a Function Compute instance. Establishing a database connection belongs to a cold start overhead at the application layer. To optimize the function performance and avoid establishing the database connection repeatedly due to multiple subsequent requests, we put this operation under the initializer to maintain the database connection during the lifecycle of a Function Compute instance.

    • Why is using an initializer better than using a global variable for the initialization?

      Within the lifecycle of a Function Compute instance, the initializer runs only once before the request to call the function. However, using the global variable affects the performance during the cold start on some occasions, such as calling a new Function Compute instance, upgrading code, periodic recycling for Function Compute, or updating containers.

  3. Create a template.yml file, such as /tmp/code/template.yml, and enter the content as follows:

    1. ROSTemplateFormatVersion: '2015-09-01'
    2. Transform: 'Aliyun::Serverless-2018-04-03'
    3. Resources:
    4. FunDemo:
    5. Type: 'Aliyun::Serverless::Service'
    6. pythondemo:
    7. Type: 'Aliyun::Serverless::Function'
    8. Properties:
    9. Handler: index.handler
    10. Runtime: python3
    11. CodeUri: '. /'
  4. Install dependencies in the /tmp/code folder.

    If you do not use a Docker environment or the dynamic library in .so format, or do not compile binary programs, to only install language dependencies, you can run the command pip install -t . PyMySQL to install. This way to install PyMySQL increases the size of the code package, because the Python libraries are downloaded regardless of whether they have been installed.

    If you use the Docker environment, we recommend that you use Fun to install third-party libraries, to debug locally, and to publish functions. Note that for the Windows operating system, use Docker for Windows. This prevents problems caused by inconsistencies between the development environment and the runtime environment. Particularly, when the function depends on binary and dynamic library files, you must use Fun to compile relevant dependencies.

    Using Fun to install PyMySQL is simple. You only need to run the command in the project folder. The following example demonstrates how to install PyMySQL in the /tmp/code folder:

    1. fun install --runtime python3 --package-type pip PyMySQL

    Notes for using Fun:

    1. Install Docker to run Fun commands. For more information about how to install Docker, see Related documents.
    2. Images that you require for running Fun are stored in Docker’s official repositories. Accessing these repositories can be slow. We recommend that you use Alibaba Cloud Container Registry. For more information, see Related documents.
    3. Only root users can run Docker in the Linux operating system. Therefore, run the sudo command to enable command line tools. Alternatively, you can manage Docker as a non-root user according to Related documents.

    After the installation, the content of the /tmp/code folder is as follows:

    1. $ ls -al /tmp/code
    2. drwxr-xr-x 3 tan wheel 96 Jun 18 17:08 .fun
    3. -rw-r--r-- 1 tan wheel 560 Jun 18 16:13 index.py

    The .fun folder is where the installed dependencies of PyMySQL are.

    If a problem occurs during the installation, you can specify the -v parameter to view more detailed logs:

    1. $ fun install -v --runtime python3 --package-type pip PyMySQL
    2. skip pulling image aliyunfc/runtime-python3.6:build-1.5.3...
    3. Task => [UNNAMED]
    4. => PYTHONUSERBASE=/code/.fun/python pip install --user PyMySQL
    5. Looking in indexes: http://mirrors.aliyun.com/pypi/simple/
    6. Collecting PyMySQL
    7. Downloading http://mirrors.aliyun.com/pypi/packages/ed/39/15045ae46f2a123019aa968dfcba0396c161c20f855f11dea6796bcaae95/PyMySQL-0.9.3-py2.py3-none-any.whl (47kB)
    8. Installing collected packages: PyMySQL
    9. Successfully installed PyMySQL-0.9.3

    For more information about the fun install command, see this topic.

  5. Use Fun to deploy

    1. fun deploy

    Note: You can use the fun install command to install the dynamic library in .so format. The following example demonstrates how to use the fun install command to install the libzbar0 file:

    1. fun install --runtime python3 --package-type apt libzbar0

    The dependencies are installed into the .fun folder after you run the command. You can use Fun to debug and deploy locally.

    Note: Dependencies are installed in the .fun folder, and therefore you must make sure that CodeUri in the template.yml file includes this folder, and it must be a top-level subfolder.

Run external commands

Functions may use some tools that are not written in Python, such as shell scripts or executable files that are complied in C++ or Go. You can still package these tools and the function code together and use them by running external commands in the functions. The following example demonstrates how to run a shell script:

  1. import os
  2. import subprocess
  3. def my_handler(event, context):
  4. script_path = os.environ.get('FC_FUNC_CODE_PATH') + '/script.sh'
  5. ret = subprocess.check_output(['bash', script_path])
  6. return ret

Executable files that are compiled in C, C++, or Go must be compatible with the runtime environment of Function Compute. The following Python runtime environments are supported in Function Compute:
  • Linux kernel version: Linux 4.4.24-2.al7.x86_64
  • Docker base image: Docker Pull Python:2.7; Docker Pull Python:3.6

We recommend that you use Fun for the installation. The following example installs mysql-python with .so files in the runtime environment Python 2.7.

You can run the fun install -- runtime python2.7 -- package-type pip mysql-python command in the code folder to install dependencies. Note that it may take a long time to run this command for the first time because the command needs to pull image. Dependencies that include the mysql.so file are installed in the .fun folder. You only need to configure CodeUri in the template.yml file to include the .fun folder and the code.

Handle exceptions

If an exception occurs during function running, Function Compute captures the exception and returns an error message. For example, in the following code:

  1. def my_handler(event, context):
  2. raise Exception('something is wrong')

When the function is called, the following response is returned:

  1. {
  2. "errorMessage": "something is wrong",
  3. "errorType": "Exception",
  4. "stackTrace": [
  5. [
  6. "File \"/code/index.py\"",
  7. "line 2",
  8. "in my_handler",
  9. "raise Exception('something is wrong')"
  10. ]
  11. ]
  12. }

When an exception occurs, the HTTP header in the response message of the call contains X-Fc-Error-Type: UnhandledInvocationError.For the error types of Function Compute, see Error types.

Contact us if you require any assistance.