Google Cloud Platform API for Python 和 AWS Lambda 不兼容:无法导入名称'cygrpc'



我正在尝试使用AWS Lambda为Python使用Google云平台(特别是Vision API)。因此,我必须为我的依赖项创建一个部署包。然而,当我尝试创建这个部署包时,无论Python的版本是3.6还是2.7,我都会遇到几个编译错误。考虑到3.6版本,我会遇到"无法导入名称‘cygrpc’"的问题。对于2.7,我在.path文件中遇到了一些未知错误。我在这里遵循AWS Lambda部署包的说明。他们推荐两种选择,但都不起作用/导致相同的问题。GCP是否因为某种原因与AWS Lambda不兼容?怎么回事?

Python 3.6和2.7都不适合我。

注意:我在这里发布这个问题是为了自己回答,因为我花了很长时间才找到解决方案,我想分享我的解决方案。

TL;DR:您无法在Mac或您使用的任何pc上编译部署包。你必须使用特定的OS/"设置"来完成这项工作,AWS Lambda使用该设置来运行你的代码。要做到这一点,您必须使用EC2。

我将在这里提供一个关于如何让谷歌云视觉在AWS Lambda for Python 2.7上工作的答案。这个答案可能可扩展到AWS Lambda上的其他API和其他编程语言。

因此,我的解决之旅始于Github上与其他有同样问题的人的首次发布。有人发布的一个解决方案是

我在运行时遇到了同样的问题"无法导入名称'cygrpc'"λ。用pip在AMI中安装谷歌云视觉解决了这个问题amzn-ami-hvm-2017.03.1.20170812-x86_64-gp2实例,并导出lib/python3.6/site-packages到aws lambda谢谢@tseaver

这是部分正确的,除非我读错了,但不管怎样,它让我走上了正确的道路。您必须使用EC2。以下是我采取的步骤:

  1. 通过访问亚马逊上的EC2来设置EC2实例。如果你还没有快速阅读有关AWS EC2的内容。为amzn-ami-hvm-2018.03.0.20180811-x86_64-gp2或类似的东西设置一个(即最新的)
  2. 获取EC2.pem文件。前往您的航站楼。cd放入.pem文件所在的文件夹中。使用将ssh放入实例中

    ssh-i"您的文件名在这里.pem"ec2-user@ec2-ip-address-here.compute-1.amazonaws.com

  3. 使用mkdir在实例上创建以下文件夹:google cloud vision、protobuf、google api python client、httplib2、uritemplate、google-auth-httplib2。

  4. 在您的EC2实例上,cd进入谷歌云视觉。运行命令:

    pip安装谷歌云视觉-t。

注意如果得到"bash:pip:commandnot found",则输入"sudo easy_install pip"source。

  1. 对以下包重复步骤4,同时cd’ing到相应的文件夹中:protobuf、google-api-python客户端、httplib2、uritemplate、google-auth-httplib2。

  2. 复制计算机上的每个文件夹。可以使用scp命令执行此操作。同样,在你的终端中,而不是你的EC2实例,也不是你用来访问EC2实例的终端窗口中,运行命令(下面是你的"谷歌云视觉"文件夹的例子,但对每个文件夹重复这个):

    sudo scp-r-i your-pem-file-name.pemec2-user@ec2-ip-address-here.compute-1.amazonaws.com:~/谷歌云视觉~/文档/您的本地目录/

  3. 从AWS控制台停止您的EC2实例,这样您就不会被多收费。

  4. 对于您的部署包,您需要一个包含所有模块和Python脚本的文件夹。要开始组合所有模块,请创建一个名为"模块"的空文件夹。将"谷歌云视觉"文件夹的所有内容复制并粘贴到"模块"文件夹中。现在,只将"protobuf"(原文如此)主文件夹中名为"protobuf"的文件夹放在"modules"文件夹的"Google"文件夹中。同样从"protobuf"主文件夹中,将protobuf.pth文件和-info文件夹粘贴到Google文件夹中。

  5. 对于protobuf之后的每个模块,将标题为模块名称的文件夹、.pth文件和-info文件夹复制并粘贴到"modules"文件夹中。

  6. 现在,您已经将所有模块正确组合(几乎)。要完成组合,请从"模块"文件夹中删除这两个文件:googleapis_common_protos-1.5-nspkg.pth和google_cloud_vision-0.34.0-py3.6-nspkg-pth。将"模块"中的所有内容复制并粘贴到部署包文件夹中。此外,如果您使用的是GCP,请将您的凭据粘贴到.json文件中。

  7. 最后,将您的Python脚本放在这个文件夹中,压缩内容(而不是文件夹),上传到S3,并将链接粘贴到AWS Lambda函数中,然后开始!

如果这里的某些东西无法按描述工作,请原谅我,并给我发信息或随时编辑我的答案。希望这能有所帮助。

根据@Josh Wolff的回答(非常感谢,顺便说一句!),可以通过使用亚马逊提供的Lambdas的Docker图像来简化这一过程。

您可以将库与项目源捆绑在一起,也可以像我下面在Makefile脚本中所做的那样,将其作为AWS层上传。

layer:
set -e ;
docker run -v "$(PWD)/src":/var/task "lambci/lambda:build-python3.6" /bin/sh -c "rm -R python; pip install -r requirements.txt -t python/lib/python3.6/site-packages/; exit" ;
pushd src ;
zip -r my_lambda_layer.zip python > /dev/null ;
rm -R python ;
aws lambda publish-layer-version --layer-name my_lambda_layer --description "Lambda layer" --zip-file fileb://my_lambda_layer.zip --compatible-runtimes "python3.6" ;
rm my_lambda_layer.zip ;
popd ;

上述脚本将:

  1. 如果您还没有Docker镜像,请提取它(上面使用Python 3.6)
  2. 删除python目录(仅适用于运行第二个时间)
  3. 将所有需求安装到在projects/src目录中创建的python目录中
  4. 压缩python目录
  5. 上传AWS层
  6. 删除python目录和zip文件

确保您的requirements.txt文件包括Josh上面列出的模块:谷歌云视觉、protobuf、谷歌api python客户端、httplib2、uritemplate、谷歌auth-httplib2

有一个不需要太多编码的快速解决方案。

Cloud9使用AMI,因此在其虚拟环境中使用pip应该可以使其工作。

我从Cloud9 UI创建了一个Lambda,并从控制台激活了EC2机器的venv。我开始用pip安装谷歌云语音。这足以解决问题。

我在使用goolge-ads API时遇到了相同的错误。

{"errorMessage":"无法导入模块"lambda_function":无法从"grpc"导入名称"ygrpc"_cython’(/var/task/grpc/_cython/init.py)"errorType":"Runtime.ImportModuleError"stackTrace":[]}

我的Lambda运行时是Python 3.9和体系结构x86_64。

如果有人遇到类似的ImportModuleError,请在此处查看我的答案:无法导入名称';cygrpc';来自';grpc_cython';-谷歌广告API

最新更新