AWS Lambda不导入LXML

use*_*827 7 python lxml amazon-web-services aws-lambda

我正在尝试在AWS Lambda中使用LXML模块并且没有运气.我使用以下命令下载了LXML:

pip install lxml -t folder
Run Code Online (Sandbox Code Playgroud)

将其下载到我的lambda函数部署包.我将lambda函数的内容压缩了所有其他lambda函数,然后将其上传到AWS Lambda.

但无论我尝试什么,我运行该函数时都会收到此错误:

Unable to import module 'handler': /var/task/lxml/etree.so: undefined symbol: PyFPE_jbuf
Run Code Online (Sandbox Code Playgroud)

当我在本地运行时,我没有问题,只是当我在Lambda上运行时出现这个问题.

Mas*_*ask 7

我遇到了同样的问题.

RaphaëlBraud发布的链接很有帮助,这个链接也是如此:https: //nervous.io/python/aws/lambda/2016/02/17/scipy-pandas-lambda/

使用这两个链接,我能够成功导入lxml和其他所需的包.以下是我遵循的步骤:

  • 使用Amazon Linux ami启动ec2机器
  • 运行以下脚本以累积依赖项:

    set -e -o pipefail
    sudo yum -y upgrade
    sudo yum -y install gcc python-devel libxml2-devel libxslt-devel
    
    virtualenv ~/env && cd ~/env && source bin/activate
    pip install lxml
    for dir in lib64/python2.7/site-packages \
         lib/python2.7/site-packages
    do
    if [ -d $dir ] ; then
       pushd $dir; zip -r ~/deps.zip .; popd
    fi
    done  
    mkdir -p local/lib
    cp /usr/lib64/ #list of required .so files
    local/lib/
    zip -r ~/deps.zip local/lib
    
    Run Code Online (Sandbox Code Playgroud)
  • 创建链接中指定的处理程序和工作程序文件.示例文件内容:

handler.py

import os
import subprocess


libdir = os.path.join(os.getcwd(), 'local', 'lib')

def handler(event, context):
    command = 'LD_LIBRARY_PATH={} python worker.py '.format(libdir)
    output = subprocess.check_output(command, shell=True)

    print output

    return
Run Code Online (Sandbox Code Playgroud)

worker.py:

import lxml

def sample_function( input_string = None):
    return "lxml import successful!"

if __name__ == "__main__":
    result = sample_function()
    print result
Run Code Online (Sandbox Code Playgroud)
  • 将处理程序和worker添加到zip文件中.

以下是上述步骤后zip文件的结构:

deps 
??? handler.py
??? worker.py 
??? local
?   ??? lib
?       ??? libanl.so
?       ??? libBrokenLocale.so
|       ....
??? lxml
?   ??? builder.py
?   ??? builder.pyc
|       ....
??? <other python packages>
Run Code Online (Sandbox Code Playgroud)
  • 确保在创建lambda函数时指定正确的处理程序名称.在上面的例子中,它将是 - "handler.handler"

希望这可以帮助!


Foo*_*ofy 5

扩展这些答案,我发现以下方法效果很好。

这里的重点是让 python 用静态库编译 lxml,并安装在当前目录而不是站点包中。

这也意味着你可以像往常一样编写你的 python 代码,而不需要一个不同的 worker.py 或摆弄 LD_LIBRARY_PATH

sudo yum groupinstall 'Development Tools'
sudo yum -y install python36-devel python36-pip
sudo ln -s /usr/bin/pip-3.6 /usr/bin/pip3
mkdir lambda && cd lambda
STATIC_DEPS=true pip3 install -t . lxml
zip -r ~/deps.zip *
Run Code Online (Sandbox Code Playgroud)

要将其提升到一个新的水平,请使用无服务器和 docker 来处理所有事情。这是一篇展示这一点的博客文章:https : //serverless.com/blog/serverless-python-packaging/


ako*_*out 5

我已经使用无服务器框架及其内置 Docker 功能解决了这个问题。

要求:您的 .aws 文件夹中有一个可以访问的 AWS 配置文件。

首先,按照此处所述安装无服务器框架。然后您可以使用命令创建配置文件serverless create --template aws-python3 --name my-lambda。它将创建一个 serverless.yml 文件和一个带有简单“hello”函数的 handler.py 文件。您可以检查这是否适用于sls deploy. 如果可行,那么无服务器就可以使用了。

接下来,我们需要一个名为“serverless-python-requirements”的附加插件来捆绑 Python 需求。您可以通过安装它sls plugin install --name serverless-python-requirements

这个插件是我们需要解决丢失的 lxml 包的所有魔法发生的地方。在 custom->pythonRequirements 部分中,您只需添加该dockerizePip: non-linux属性即可。您的 serverless.yml 文件可能如下所示:

service: producthunt-crawler

provider:
  name: aws
  runtime: python3.8

functions:
  hello:
    # some handler that imports lxml
    handler: handler.hello

plugins:
  - serverless-python-requirements

custom:
  pythonRequirements:
    fileName: requirements.txt
    dockerizePip: non-linux

    # Omits tests, __pycache__, *.pyc etc from dependencies
    slim: true
Run Code Online (Sandbox Code Playgroud)

这将在预配置的 docker 容器内运行 python 需求的捆绑。之后,您可以运行sls deploy看看奇迹发生,然后sls invoke -f my_function检查它是否有效。

当您使用无服务器进行部署并dockerizePip: non-linux稍后添加选项时,请确保使用sls requirements clean. 否则,它只是使用已经构建的东西。

  • 这是一个很好的解决方案。不过,这里有一个重要的警告让我苦恼不已:如果您在将 `dockerizePip` 选项添加到 yaml 之前一直在运行 sls deploy,则 sls 可能会继续使用您需求的缓存版本!这会导致对yaml的修改没有效果!检查您的 sls 部署输出中是否有“使用需求的静态缓存...”之类的内容,如果它这样说,则必须先删除引用的缓存文件,然后此解决方案才能起作用。 (2认同)