AWS Lambda не импортирует LXML

Я пытаюсь использовать модуль LXML в AWS Lambda и не везет. Я загрузил LXML, используя следующую команду:

pip install lxml -t folder

чтобы загрузить его в пакет развертывания моей лямбда-функции. Я застегнул содержимое моей лямбда-функции, как и со всеми другими лямбда-функциями, и загрузил его в AWS Lambda.

однако независимо от того, что я пытаюсь, я получаю эту ошибку при запуске функции:

Unable to import module 'handler': /var/task/lxml/etree.so: undefined symbol: PyFPE_jbuf

когда я запустить его локально, у меня нет проблемы, это просто, когда я сталкиваюсь с лямбда, где возникает эта проблема.

4 ответов


я столкнулся с той же проблемой.

ссылка опубликована Рафаэль Брод было полезно, и так было это: https://nervous.io/python/aws/lambda/2016/02/17/scipy-pandas-lambda/

используя две ссылки, я смог успешно импортировать lxml и другие необходимые пакеты. Вот шаги, которым я следовал:

  • запустите машину ec2 с Amazon Linux ami
  • запустите следующий скрипт для накопления зависимости:

    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
    
  • создайте обработчик и рабочие файлы, как указано в ссылке. Пример содержимого файла:

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

worker.py:

import lxml

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

if __name__ == "__main__":
    result = sample_function()
    print result
  • добавить обработчик и рабочий в zip-файл.

вот как выглядит структура zip-файла после вышеуказанных шагов:

deps 
├── handler.py
├── worker.py 
├── local
│   └── lib
│       ├── libanl.so
│       ├── libBrokenLocale.so
|       ....
├── lxml
│   ├── builder.py
│   ├── builder.pyc
|       ....
├── <other python packages>
  • убедитесь, что вы указали правильное имя обработчика при создании лямбда-функции. В приведенном выше примере, это будет- "обработчик.обработчик"

надеюсь, что это помогает!


расширяя эти ответы, я обнаружил, что следующее работает хорошо.

здесь punchline имеет компиляцию lxml python со статическими либами и установку в текущем каталоге, а не в пакетах сайта.

это также означает, что вы можете написать свой код 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 *

чтобы перейти на следующий уровень, используйте serverless и docker для обработки всего. здесь в блоге демонстрация этого: https://serverless.com/blog/serverless-python-packaging/


AWS Lambda использует специальную версию Linux (насколько я вижу).

использование "pip install a_package-t folder" является хорошей вещью, чтобы сделать обычно, так как это поможет упаковать ваши зависимости в архиве, который будет отправлен в лямбда, но библиотеки, и особенно двоичные библиотеки должны быть совместимы с версией ОС и Python на лямбда.

вы можете использовать модуль xml, включенный в Python : https://docs.python.org/2/library/xml.etree.elementtree.html

Если вам действительно нужен lxml, эта ссылка дает некоторые рекомендации по компиляции общих библиотек для Lambda : http://www.perrygeo.com/running-python-with-compiled-code-on-aws-lambda.html


немного расширяя ответ маски. В случае установки lxml в частности, библиотеки libxslt и libxml2 уже установлены на AMI, который выполняет AWS lambda. Поэтому нет необходимости запускать подпроцесс с другим LD_LIBRARY_PATH, как в этом ответе, однако необходимо запустить pip install lxml на образе AMI (возможно, также можно скомпилировать, но я не знаю, как).

Launch an ec2 machine with Amazon Linux ami
Run the following script to accumulate dependencies:
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 

обратите внимание, что последний steps from Marks answer is left out. Вы можете использовать lxml прямо из файла python, содержащего метод обработчика.