我正在尝试在AWS Lambda中使用LXML模块并且没有运气。我使用以下命令下载了LXML:
pip install lxml -t folder
将其下载到我的lambda函数部署包。我将lambda函数的内容压缩为所有其他lambda函数,然后将其上传到AWS Lambda。
然而,无论我尝试什么,我在运行该函数时都会收到此错误:
Unable to import module 'handler': /var/task/lxml/etree.so: undefined symbol: PyFPE_jbuf
当我在本地运行它时,我没有问题,只是当我在Lambda上运行时出现这个问题。
答案 0 :(得分:6)
我遇到了同样的问题。
Raphaël Braud发布的链接很有帮助,这个链接也是如此: https://nervous.io/python/aws/lambda/2016/02/17/scipy-pandas-lambda/
使用这两个链接,我能够成功导入lxml和其他必需的包。以下是我遵循的步骤:
运行以下脚本以累积依赖项:
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
创建link中指定的处理程序和工作程序文件。示例文件内容:
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文件的结构:
deps
├── handler.py
├── worker.py
├── local
│ └── lib
│ ├── libanl.so
│ ├── libBrokenLocale.so
| ....
├── lxml
│ ├── builder.py
│ ├── builder.pyc
| ....
├── <other python packages>
希望这有帮助!
答案 1 :(得分:4)
根据这些答案,我发现以下内容效果很好。
这里的妙语是使用带有静态库的python compile lxml,并安装在当前目录而不是site-packages中。
这也意味着你可以像往常一样编写你的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 *
将它带到一个新的水平,使用无服务器和docker来处理所有事情。这是一篇博客文章,展示了这一点: https://serverless.com/blog/serverless-python-packaging/
答案 2 :(得分:2)
AWS Lambda使用特殊版本的Linux(据我所见)。
使用“pip install a_package -t文件夹”通常是好事,因为它有助于将您的依赖项打包到将发送到Lambda的存档中,但是库,特别是二进制库必须兼容使用lambda上的OS和Python版本。
您可以使用Python中包含的xml模块: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
答案 3 :(得分:2)
在Mask的答案上稍微扩展一下。在特别安装lxml的情况下, libxslt和libxml2库已经安装在执行AWS lambda的AMI上。因此,不需要像在答案 中那样使用不同的LD_LIBRARY_PATH启动子进程,但是必须在AMI映像上运行pip install lxml(也可以进行交叉编译)但我不知道如何)。
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
请注意,Marks答案的最后几个步骤被忽略了。您可以直接从包含处理程序方法的python文件中使用lxml。
答案 4 :(得分:2)
我已经使用serverless框架及其内置的Docker功能解决了这个问题。
要求:.aws文件夹中有一个AWS配置文件,可以访问。
首先,按照here的说明安装无服务器框架。然后,您可以使用命令serverless create --template aws-python3 --name my-lambda
创建配置文件。它将使用简单的“ hello”功能创建一个serverless.yml文件和一个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
这将在预先配置的Docker容器中运行python需求的捆绑。之后,您可以运行sls deploy
来查看魔术的发生,然后运行sls invoke -f my_function
来检查魔术是否起作用。
以后使用无服务器部署和添加dockerizePip: non-linux
选项时,请确保使用sls requirements clean
清理已构建的需求。否则,它将仅使用已构建的东西。
答案 5 :(得分:1)
通过遵循this页上的自述文件,我可以使此工作正常进行:
python3.8
替换为用于lambda函数的python版本,将lxml
替换为您要使用的lxml的版本)
$ docker run -v $(pwd):/outputs -it lambci/lambda:build-python3.8 \
pip install lxml -t /outputs/
lxml
的文件夹,并且可能会忽略其他一些文件夹。将lxml
文件夹移至与您用作lambda处理程序的.py
文件相同的目录。.py
文件。我有一个virtualenv,而lxml已经存在于我的site-packages文件夹中,因此我必须先删除它。这是我运行的命令(请注意,我的virtualenv v-env文件夹与.py
文件位于同一目录中):
FUNCTION_NAME="name_of_your_python_file"
cd v-env/lib/python3.8/site-packages &&
rm -rf lxml &&
rm -rf lxml-4.5.1.dist-info &&
zip -r9 ${OLDPWD}/${FUNCTION_NAME}.zip . &&
cd ${OLDPWD} &&
zip -g ${FUNCTION_NAME}.zip ${FUNCTION_NAME}.py &&
zip -r9 ${FUNCTION_NAME}.zip lxml
FUNCTION_NAME="name_of_your_python_file"
zip -g ${FUNCTION_NAME}.zip ${FUNCTION_NAME}.py &&
zip -r9 ${FUNCTION_NAME}.zip lxml
有关使用virtualenv here为lambda创建.zip文件的更多信息
答案 6 :(得分:0)
lxml库是os依赖的,因此我们需要具有预编译的副本。步骤如下。
创建一个Docker容器。
docker run -it lambci/lambda:build-python3.8 bash
创建一个名为“ lib”的目录(任何您想要的目录)并将lxml安装到其中。
mkdir lib
pip install lxml -t ./lib --no-deps
打开另一个cmd并运行
docker ps
复制containerid
将文件从容器复制到主机。
mkdir /home/libraries/opt/python/lib/python3.8/site-packages/
docker cp <containerid>:/var/task/lib /home/libraries/opt/python/lib/python3.8/site-packages/
现在,如果您希望将lxml作为Lambda层,则可以从amazonlinux框中编译文件的lxml副本。导航至/home/libraries/opt
并压缩名为python
的文件夹。现在,您可以将zip附加在lambda中作为图层。
如果要在lambda中包含lxml库。导航到/home/libraries/opt/python/lib/python3.8/site-packages/
,然后将lxml
文件夹复制到您的lambda中。
答案 7 :(得分:0)
LXML对它的运行环境非常敏感。
我通过在 python:3.x-slim 容器中构建zip Lambda软件包来解决此问题:
pip install --target=. lxml
zip -r lambda.zip lambda.py lxml
图片容器版本必须与Lambda中使用的python引擎版本相同
使用python 3.6、3.7和3.8成功测试
答案 8 :(得分:0)
您可以在此处找到此项目和大多数其他项目的 whl 文件; https://pypi.org/project/lxml/#files