【问题标题】:Unable to import lxml etree on aws lambda无法在 aws lambda 上导入 lxml etree
【发布时间】:2019-11-11 02:26:01
【问题描述】:
{
  "errorMessage": "Unable to import module 'lambda_function': 
        cannot import name   'etree' from 'lxml' (/var/task/lxml/__init__.py)",
  "errorType": "Runtime.ImportModuleError"
}

也试过https://gist.github.com/allen-munsch/ad8faf9c04b72aa8d0808fa8953bc639:

{
  "errorMessage": "Unable to import module 'lambda_function': 
     cannot import name 'etree' from 'lxml' 
     (/var/task/lxml-4.3.4-py3.6-linux-x86_64.egg/lxml/__init__.py)",
  "errorType": "Runtime.ImportModuleError"
}

我在本地机器上的Ubuntu 18.04 上运行,并且还尝试使用 ec2 实例上的“Amazon Linux”映像来构建捆绑包。

我也试过,在激活的venv内:

STATIC_DEPS=true pip3 install lxml --target ./package --upgrade --no-cache-dir

我还尝试根据在使用strace 运行脚本时拉取打开的文件来复制共享对象文件:

#! /bin/bash

export Z=$(pwd)/ok-daily-lambda.zip
rm $Z
zip $Z lambda_function.py
zip $Z __init__.py

for dir in $(find venv_here/lib/python3.6/site-packages)
do
    if [ -d $dir ] ; then
        pushd $dir
        echo zip -r9 $Z $(pwd)
        zip -r9 $Z $(pwd)
        popd
    fi
done

export LIBD=$(pwd)/lib
mkdir -p $LIBD

cp "/home/jmunsch/.local/lib/python3.6/site-packages/.libs_cffi_backend/libffi-d78936b1.so.6.0.4" $LIBD
cp "/lib/x86_64-linux-gnu/libbz2.so.1.0" $LIBD
cp "/lib/x86_64-linux-gnu/libc.so.6" $LIBD
cp "/lib/x86_64-linux-gnu/libdl.so.2" $LIBD
cp "/lib/x86_64-linux-gnu/libexpat.so.1" $LIBD
cp "/lib/x86_64-linux-gnu/libgcc_s.so.1" $LIBD
cp "/lib/x86_64-linux-gnu/liblzma.so.5" $LIBD
cp "/lib/x86_64-linux-gnu/libm.so.6" $LIBD
cp "/lib/x86_64-linux-gnu/libnss_dns.so.2" $LIBD
cp "/lib/x86_64-linux-gnu/libnss_files.so.2" $LIBD
cp "/lib/x86_64-linux-gnu/libnss_mdns4_minimal.so.2" $LIBD
cp "/lib/x86_64-linux-gnu/libpthread.so.0" $LIBD
cp "/lib/x86_64-linux-gnu/libresolv.so.2" $LIBD
cp "/lib/x86_64-linux-gnu/librt.so.1" $LIBD
cp "/lib/x86_64-linux-gnu/libtinfo.so.5" $LIBD
cp "/lib/x86_64-linux-gnu/libudev.so.1" $LIBD
cp "/lib/x86_64-linux-gnu/libutil.so.1" $LIBD
cp "/lib/x86_64-linux-gnu/libuuid.so.1" $LIBD
cp "/lib/x86_64-linux-gnu/libz.so.1" $LIBD
cp "/usr/lib/x86_64-linux-gnu/libapt-pkg.so.5.0" $LIBD
cp "/usr/lib/x86_64-linux-gnu/libcrypto.so.1.1" $LIBD
cp "/usr/lib/x86_64-linux-gnu/libffi.so.6" $LIBD
cp "/usr/lib/x86_64-linux-gnu/liblz4.so.1" $LIBD
cp "/usr/lib/x86_64-linux-gnu/libmpdec.so.2" $LIBD
cp "/usr/lib/x86_64-linux-gnu/libssl.so.1.1" $LIBD
cp "/usr/lib/x86_64-linux-gnu/libstdc++.so.6" $LIBD
cp "/usr/lib/x86_64-linux-gnu/libzstd.so.1" $LIBD

zip -r $Z $LIBD

AWS_ACCESS_KEY_ID="xxx" AWS_SECRET_ACCESS_KEY="xxx" AWS_DEFAULT_REGION="us-east-1" aws lambda update-function-code --function-name ok-today --zip-file fileb://ok-daily-lambda.zip

这是最新的 zip 文件的目录结构:

相关:

【问题讨论】:

    标签: python aws-lambda


    【解决方案1】:

    我遇到了类似的问题,我想出了一个快速的解决方法

    使用 lxml 的预编译构建

    下载https://github.com/shubh2502/aws-lambda-lxml

    1. 文件夹 3.6.4 和 3.8.0 是 lxml 版本
    2. 在lxml里面有两个构建python27和python36

    3. 根据 AWS Lambda python 版本选择其中之一

    4. 在python27和python36里面有lxml文件夹

    5. 带有lxml文件夹的邮政编码,并确保python具有相同的版本

    6. 在 AWS Lambda 层的情况下将 lxml 文件夹放入此结构 -

      python/lib/python3.6/site-packages

    我花了很多时间在 docker 和构建这些东西,这个方法对我来说是救星,希望对你有所帮助

    【讨论】:

    • 我将 zip 创建为 lambda.zip,不确定 lxml 是问题还是 zip 的名称
    【解决方案2】:

    有些模块无法直接添加到 site-packages 目录中以在 AWS Lambda 环境中被识别。发生这种情况时,您必须从 Docker 存储库获取 Amazon Linux 映像,并在将在 AWS Lambda 上运行的容器版本中创建自己的编译环境

    例如,如果您想使用 Python 3.6,一个不错的选择是 amazonlinux:2018.03,以防您想安装更多软件包,例如熊猫,numpy,scipy

        docker run -v $(pwd):/outputs -it amazonlinux:2018.03
    

    由于 Amazon Linux 基于 Red Hat,因此在运行 docker 并已创建虚拟环境时,您必须通过 yum 安装所有依赖项

        yum update -y
        yum install -y \
          python36 \
          python36-devel \
          python36-virtualenv \
          python34-setuptools \
          gcc \
          gcc-c++ \
          findutils \
          rsync \
          Cython \
          findutils \
          which \
          gzip \
          tar \
          man-pages \
          man \
          wget \
          make \
          zip
    

    对于lxml,您还需要

        (lambda_docker) bash-4.2# yum install libxml2
        ...
        (lambda_docker) bash-4.2# yum install libxslt
        ...
    

    你照常安装模块

        pip3.6 install lxml
    

    你应该看到类似的东西

        (lambda_docker) bash-4.2# pip3.6 install lxml
        Collecting lxml
          Downloading https://files.pythonhosted.org/packages/2d/53/34a9f0c79c548e430148837892b6ae91adee571a0e8b6c17bd7ff9c2d12e/lxml-4.3.4-cp36-cp36m-manylinux1_x86_64.whl (5.7MB)
             |################################| 5.7MB 2.0MB/s 
        Installing collected packages: lxml
    

    然后,创建您的函数lambda_function.py 并将其添加到您的 docker 会话中推送和弹出的压缩包中

        from lxml import etree
    
        def lambda_handler(event, context):
            print(__name__)
            print(etree.LXML_VERSION)
    

    创建后

        zip -g site-packages.zip lambda_function.py
    

    在上传之前,您可以检查您的 zip 文件是否包含 lxml 目录

        [jonathan@docker lambda_docker]$ unzip -l site-packages.zip 
        Archive:  site-packages.zip
          Length      Date    Time    Name
        ---------  ---------- -----   ----
                0  06-29-2019 23:09   __pycache__/
              277  06-29-2019 23:09   __pycache__/easy_install.cpython-36.pyc
              126  06-29-2019 23:09   easy_install.py
              119  06-29-2019 23:29   lambda_function.py
                0  06-29-2019 23:21   lib/
                0  06-29-2019 23:39   lxml/
                0  06-29-2019 23:37   lxml-4.3.4.dist-info/
                4  06-29-2019 23:37   lxml-4.3.4.dist-info/INSTALLER
             2954  06-29-2019 23:37   lxml-4.3.4.dist-info/METADATA
            13384  06-29-2019 23:37   lxml-4.3.4.dist-info/RECORD
              109  06-29-2019 23:37   lxml-4.3.4.dist-info/WHEEL
                5  06-29-2019 23:37   lxml-4.3.4.dist-info/top_level.txt
             7668  06-29-2019 23:37   lxml/ElementInclude.py
              551  06-29-2019 23:37   lxml/__init__.py
                0  06-29-2019 23:37   lxml/__pycache__/
             3331  06-29-2019 23:37   lxml/__pycache__/ElementInclude.cpython-36.pyc
        ...
    

    现在上传 zip 并在您的 lambda 函数中创建一个空测试 {}

    结果

        START RequestId: bb240a17-c2dd-4d63-92c8-fa7561c09f64 Version: $LATEST
        lambda_function
        (4, 3, 4, 0)
        END RequestId: bb240a17-c2dd-4d63-92c8-fa7561c09f64
        REPORT RequestId: bb240a17-c2dd-4d63-92c8-fa7561c09f64  Duration: 0.30 ms   Billed Duration: 100 ms     Memory Size: 128 MB Max Memory Used: 50 MB  
    

    如果你喜欢图片

    为 AWS Lambda 做好充分准备

    希望对你有帮助(:

    【讨论】:

    • 抱歉,没有误导的意思。
    【解决方案3】:

    原因:

    在不同操作系统上编译的.so 文件。 (在我的情况下是 macOS。)

    解决办法:

    以下文章非常有帮助:

    How do I create a Lambda layer using a simulated Lambda environment with Docker?

    我所要做的就是:

    cd /path_to_requirements_txt/
    
    docker run -v "$PWD":/var/task "lambci/lambda:build-python3.7" /bin/sh -c "pip install -r requirements.txt -t python/lib/python3.7/site-packages/; exit"
    

    它创建了带有所有依赖项的python/lib/python3.7/site-packages/

    【讨论】:

      【解决方案4】:

      如果您使用 SERVERLESS 进行部署:

      然后,检查您本地环境中的 python 版本以及您正在使用的 lambda 运行时版本

      我在本地使用 Python 3.8,而 lambda 运行时版本使用的是 Python 3.7 所以我将 lambda 版本更改为使用 Python 3.8

      这对我有用!!!

      希望对你有帮助

      【讨论】:

        猜你喜欢
        • 2012-08-17
        • 2021-05-29
        • 2014-03-13
        • 1970-01-01
        • 2016-07-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多