Python 中 AWS Lambda 和 Open CV 的无服务器问题

Serverless issue with AWS Lambda and Open CV in Python

我正在开发一个微服务来分析上传到 S3 AWS Bucket 的图像。我正在使用无服务器框架。我正在使用 virtualenv 通过 PIP 和 serverless-python-requirements 插件安装依赖项,以将这些依赖项部署到 Lambda 函数。

但是,由于缺少 .so 文件,我在部署微服务时遇到错误。我得到的错误是

无法导入模块'handlers.image': libgthread-2.0.so.0: 无法打开共享对象文件: 没有这样的文件

我的serverless.yml文件是

service: sls-covid

provider:
  name: aws
  runtime: python3.8
  profile: testuser
  stage: ${opt:stage, 'staging'}
  environment: ${file(environment.yml):${self:provider.stage}}
  region: ${self:provider.environment.REGION}

  iamRoleStatements:
    # para poder leer y escribir en el bucket
    - Effect: "Allow"
      Action:
        - "s3:*"
      Resource: "*"

custom:
  pythonRequirements:
    dockerizePip: non-linux


package:
  individually: true
  exclude:
    - node_modules/**
    - env/**
    - package.json
    - package-lock.json

functions:

  analyzeImage:
    # para analizar la imagen cuando se almacena en S3
    handler: handlers.image.analyze
    events:
      - s3:
          bucket: ${self:service}-${self:provider.stage}-images
          event: s3:ObjectCreated:*
          rules:
            - prefix: uploads/

plugins:
  - serverless-python-requirements

相关代码为:

import json
import logging
import boto3
from pydicom import dcmread
import numpy as np
# here the code stops working
import cv2
from pydicom.filebase import DicomBytesIO

logger = logging.getLogger()
logger.setLevel(logging.INFO)

s3 = boto3.client('s3')


def analyze(event, context):

    print("=== event: ", event)

    # code to read uploaded image from bucket and create a ds object 

    # code below is never executed since the error appears when the cv2 library is loaded  

    img = cv2.resize(ds.pixel_array, (224, 224))

而我的requirements.txt内容如下:

numpy==1.18.4
opencv-python==4.2.0.34
pandas==1.0.3
pydicom==1.4.2
python-dateutil==2.8.1
pytz==2018.7
six==1.14.0

我的问题是。如何使用插件将 opencv 依赖项正确上传到我的 lambda 函数?我应该换一种方式吗?

谢谢!

基于 doc,您需要使用 dockerExtraFiles 选项手动包含这些内容。

=======================更新===================== ==

为 AWS Lambda 打包 Python 依赖项和构建部署包可能非常棘手。在四处挖掘之后,这里是你需要做的事情才能让它发挥作用。

第 1 步:添加 Dockerfile

FROM lambci/lambda:build-python3.8
RUN yum -y install libXext libSM libXrender

第 2 步:修改 serverless.yml

service: sls-covid

provider:
  name: aws
  runtime: python3.8
  profile: testuser
  stage: ${opt:stage, 'staging'}
  environment: ${file(environment.yml):${self:provider.stage}}
  region: ${self:provider.environment.REGION}

  iamRoleStatements:
    # para poder leer y escribir en el bucket
    - Effect: "Allow"
      Action:
        - "s3:*"
      Resource: "*"

custom:
  pythonRequirements:
    dockerizePip: non-linux
    ########### BEGIN ###########
    dockerFile: Dockerfile
    dockerExtraFiles:
      - /lib64/libgthread-2.0.so.0
      - /lib64/libglib-2.0.so.0
      - /lib64/libSM.so.6
      - /lib64/libICE.so.6
      - /lib64/libXrender.so.1
      - /lib64/libXext.so.6
      - /lib64/libX11.so.6
      - /lib64/libuuid.so.1
      - /lib64/libxcb.so.1
      - /lib64/libXau.so.6
    ########### END ###########


package:
  individually: true
  exclude:
    - node_modules/**
    - env/**
    - package.json
    - package-lock.json

functions:

  analyzeImage:
    # para analizar la imagen cuando se almacena en S3
    handler: handlers.image.analyze
    events:
      - s3:
          bucket: ${self:service}-${self:provider.stage}-images
          event: s3:ObjectCreated:*
          rules:
            - prefix: uploads/

plugins:
  - serverless-python-requirements

第 3 步:Hello world 测试

$ sls invoke -f analyzeImage --log
null
--------------------------------------------------------------------
START RequestId: 00ccd940-cf8a-46ed-8671-65e597f997a0 Version: $LATEST
=== event:  {}
END RequestId: 00ccd940-cf8a-46ed-8671-65e597f997a0
REPORT RequestId: 00ccd940-cf8a-46ed-8671-65e597f997a0  Duration: 1.41 ms   Billed Duration: 100 ms Memory Size: 1024 MB    Max Memory Used: 121 MB Init Duration: 916.32 ms

希望对您有所帮助。

我运行陷入同样的​​问题。我偶然做的是:

  1. 在 ec2 linux 实例上开发。这要容易得多,因为您 运行 在部署之前的开发过程中遇到了所有错误。
  2. 找到丢失的.so 文件。寻找 。 -name "libgthread-2.0.so.0"
  3. 在名为“lib”的项目主页中创建一个名为 lib 的目录。此文件夹包含在 LD_LIBRARY_PATH.
  4. 将所需的 libgthread-2.0.so.0 文件复制到 lib 文件夹中。
  5. sls 部署。 现在找到了丢失的 .so 文件。