全部产品
弹性计算 会员服务 网络 安全 移动云 数加·大数据分析及展现 数加·大数据应用 管理与监控 云通信 阿里云办公 培训与认证 智能硬件
存储与CDN 数据库 域名与网站(万网) 应用服务 数加·人工智能 数加·大数据基础服务 互联网中间件 视频服务 开发者工具 解决方案 物联网 更多
函数计算

Python 运行环境

更新时间:2018-06-22 23:31:34

函数计算目前支持以下 Python 运行环境:

  • Python 2.7 ( runtime = python2.7 )
  • Python 3.6 ( runtime = python3 )

本文分以下几个部分对 Python 的运行环境进行介绍:

使用logging

函数向 stdout 打印的内容会被收集到创建 service 时指定的 Logstore 中,有两种打 log 的方法:

  1. 直接使用print: 这会把内容原样地输出到日志中。

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

    上面的代码输出的日志内容是:

    1. message:hello world
  2. 使用 logging 模块: 这会在每条日志中包含时间 / requestId / 日志级别等信息。

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

    上面的代码输出的日志内容是:

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

推荐使用 logging 模块打印 log,自动包含 requestId 能信息方便在出错的时候定位问题日志。

使用内置模块

除了 Python 的标准模块,函数计算的 Python 运行环境中还包含了一些常用模块,用户可以直接引用,目前包含的模块有:

模块名称 模块介绍 相关链接
oss2 2.3.3 OSS SDK https://github.com/aliyun/aliyun-oss-python-sdk
tablestore 4.3.4 表格存储 SDK https://github.com/aliyun/aliyun-tablestore-python-sdk
aliyun-fc2 2.0.4 函数计算 SDK https://github.com/aliyun/fc-python-sdk
aliyun-mns 1.1.5 消息服务 https://github.com/bowenpay/mns-python-sdk
aliyun-python-sdk-cdn 2.6.2 CDN 服务 https://github.com/aliyun/aliyun-openapi-python-sdk/tree/master/aliyun-python-sdk-cdn
aliyun-python-sdk-ram 3.0.0 访问控制 RAM https://github.com/aliyun/aliyun-openapi-python-sdk/tree/master/aliyun-python-sdk-ram
aliyun-python-sdk-sts 3.0.0 访问控制 STS https://github.com/aliyun/aliyun-openapi-python-sdk/tree/master/aliyun-python-sdk-sts
aliyun-log-python-sdk 0.6.24 日志服务 SLS https://github.com/aliyun/aliyun-log-python-sdk
wand 0.4.4 图片处理库 http://docs.wand-py.org/en/0.4.4/
opencv 3.3.0.10 计算机视觉库 http://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_setup/py_intro/py_intro.html
numpy 1.13.3 科学计算库 http://www.numpy.org/
scipy 1.0.0 科学计算库 https://www.scipy.org/
matplotlib 2.0.2 绘图库 https://matplotlib.org/
scrapy 1.4.0 数据抓取库 https://scrapy.org/

例如使用 wand 进行图片翻转的函数如下:

  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()

注意:上面的函数直接使用 event 作为图片的二进制数据并且直接把生成的图片作为二进制数据返回。

tips: 还有其他第三方库使用的小 demo 可以查看这里 fc-python-demo

使用自定义的模块

如果用户需要使用自定义的模块,则需要将它们与代码一起打包。下面将演示通过 fcli 添加一个访问 mysql 的模块 PyMySQL 的步骤:

  1. 建立一个目录用于存放代码和依赖模块:
    1. mkdir /tmp/code
  2. 新建代码文件,例如 /tmp/code/main.py,在代码中使用 pymysql:

    1. import pymysql.cursors
    2. # Connect to the database
    3. connection = pymysql.connect(host='localhost',
    4. user='user',
    5. password='passwd',
    6. db='db',
    7. charset='utf8mb4',
    8. cursorclass=pymysql.cursors.DictCursor)
    9. def my_handler(event, context):
    10. with connection.cursor() as cursor:
    11. # Read a single record
    12. sql = "SELECT count(*) FROM `users`"
    13. cursor.execute(sql)
    14. result = cursor.fetchone()
    15. print(result)
    16. return result
  3. 在 /tmp/code 目录下安装依赖。

    1. cd /tmp/code
    2. pip install --install-option="--install-lib=$(pwd)" PyMySQL

    利用 pip install -t . PyMySQL, 会把 PyMySQL 依赖的 python 库都会下载下来,不管环境中是否安装了这些 python 库,如果不是对依赖的 module 有严格的版本要求,建议有优先使用 install-option 参数的方法,因为这个方法不会在本地重复下载环境中已有的 python 库,会大大减少本地第三方包的大小, 如下图所示(红线框住的本地不会重新下载):py-install

    安装完成之后,/tmp/code 目录的内容应该是这样:

    1. ls -l /tmp/code
    2. drwxr-xr-x 9 rockuw staff 306 Jul 5 16:48 PyMySQL-0.7.11.dist-info
    3. -rw-r--r-- 1 rockuw staff 74 Jul 5 16:02 main.py
    4. drwxr-xr-x 26 rockuw staff 884 Jul 5 16:48 pymysql
  4. 使用 fcli 创建函数并调用。

    1. ./fcli shell
    2. mkf my-func -h main.my_handler --runtime python2.7 -d /tmp/code
    3. invk my-func
需要注意的是,如果引用的 module 使用 C / C++ / go 编译出来的可执行文件或者库文件,请查看 sbox

调用外部命令

用户的函数可能会用到一些工具,而这些工具并不是用 Python 写的(例如 shell 脚本 / C++ 或者 go 编译出来的可执行文件)。用户仍然可以将它们与代码一起打包,然后在函数中通过运行外部命令的方法来使用它们。下面的例子中演示了如何运行一个 shell 脚本:

  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

需要注意的是,使用 C / C++ / go 编译出来的可执行文件,需要与函数计算的运行环境兼容。函数计算的 Python 运行环境是:
  • Linux 内核版本:Linux 4.4.24-2.al7.x86_64
  • docker 基础镜像:docker pull python:2.7 ; docker pull python:3.6

推荐使用 fcli 工具 sbox 命令,下面以 runtime 为 python2.7,安装 mysql-python (含有 .so 文件)为例:

  1. 执行 sbox -d code -t python2.7 ,其中 -d 参数指定代码所在目录,它将被挂载到沙盒环境的 “/code” 位置;-t 参数指定语言类型;(注:第一次执行这个命令由于要 pull image ,可能要耗费不少时间,请耐心等待…)。

  2. 进入沙盒环境后,运行 pip install -t . mysql-python 安装依赖库。

  3. 完成后执行 exit 退出沙盒环境。此时 mysql-python 库 (含有 _mysql.so ) 已经安装到了 code 目录下。

注意

  1. sbox 命令要求您的机器上已安装 docker。docker 的具体安装步骤,请参阅 相关文档

  2. sbox 用到的镜像存储在 docker 官方镜像库上,国内用户访问速度较慢。建议您使用阿里云镜像加速服务,具体设置请参阅 相关文档

  3. 在 linux 下使用 docker,要求有 root 权限。所以您需要使用 sudo fcli shell 的方式启动命令行工具;或者您可以参照 相关文档 设置,以非 root 用户管理 docker。

  4. 推荐您总是在沙盒环境中打包第三方库,测试函数和调查问题,这样能避免由于开发环境和运行环境不一致所引起的一些问题。特别是当您的函数依赖二进制文件时,请在沙盒环境中编译相关依赖。

  1. songluo@demo $ fcli shell
  2. Welcome to the function compute world. Have fun!
  3. >>> sbox -d code -t python2.7
  4. Entering the container. Your code is in the /code direcotry.
  5. root@c5adc6ffd861:/code# pip install -t . mysql-python
  6. Collecting mysql-python
  7. Downloading MySQL-python-1.2.5.zip (108kB)
  8. 100% |████████████████████████████████| 112kB 440kB/s
  9. Building wheels for collected packages: mysql-python
  10. Running setup.py bdist_wheel for mysql-python ... done
  11. Stored in directory: /root/.cache/pip/wheels/38/a3/89/ec87e092cfb38450fc91a62562055231deb0049a029054dc62
  12. Successfully built mysql-python
  13. Installing collected packages: mysql-python
  14. Successfully installed mysql-python-1.2.5
  15. root@c5adc6ffd861:/code# exit

如果您的依赖中包含 .so 等动态链接文件,需要将其放到当前目录的 lib 目录下,因为函数计算的执行环境会将 lib 目录放到 path 中

错误处理

函数在执行过程如果抛出异常,那么函数计算会把异常捕获并将异常信息返回。例如下面的代码:

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

调用时收到的响应为:

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

发生异常时,函数调用的响应的 HTTP header 中会包含 X-Fc-Error-Type: UnhandledInvocationError。关于函数计算的错误类型请参考文章 错误类型

您在使用过程中遇到任何问题请 联系我们

本文导读目录