适用于 Python 和 AWS Lambda 的 Google Cloud Platform API 不兼容:无法导入名称“cygrpc”

Posted

技术标签:

【中文标题】适用于 Python 和 AWS Lambda 的 Google Cloud Platform API 不兼容:无法导入名称“cygrpc”【英文标题】:Google Cloud Platform API for Python and AWS Lambda Incompatibility: Cannot import name 'cygrpc' 【发布时间】:2019-03-25 13:53:39 【问题描述】:

我正在尝试将适用于 Python 的 Google Cloud Platform(特别是 Vision API)与 AWS Lambda 结合使用。因此,我必须为我的依赖项创建一个部署包。但是,当我尝试创建此部署包时,无论 Python 的版本是什么(3.6 或 2.7),都会出现一些编译错误。考虑到 3.6 版,我收到“无法导入名称 'cygrpc'”的问题。对于 2.7,.path 文件出现一些未知错误。我正在遵循 AWS Lambda 部署包说明here。他们推荐了两个选项,两者都不起作用/导致相同的问题。 GCP 是否出于某种原因与 AWS Lambda 不兼容?有什么关系?

Python 3.6 和 2.7 都不适合我。

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

【问题讨论】:

【参考方案1】:

TL;DR:您无法在您的 Mac 或您使用的任何电脑上编译部署包。您必须使用特定的操作系统/“设置”来执行此操作,这与 AWS Lambda 用于运行您的代码的设置相同。为此,您必须使用 EC2。

我将在此处提供有关如何让 Google Cloud Vision 在 AWS Lambda for Python 2.7 上运行的答案。对于 AWS Lambda 上的其他 API 和其他编程语言,此答案可能是可扩展的。

因此,我的解决方案之旅始于 Github 上的 this initial posting,其他人也有同样的问题。有人发布的一种解决方案是

我在运行时遇到了同样的问题“无法导入名称 'cygrpc'” 拉姆达。在 AMI 中使用 pip install google-cloud-vision 解决了这个问题 amzn-ami-hvm-2017.03.1.20170812-x86_64-gp2 实例并导出 lib/python3.6/site-packages 到 aws lambda 谢谢@tseaver

这是部分正确的,除非我读错了,但不管它引导我走上正确的道路。您将不得不使用 EC2。以下是我采取的步骤:

    通过转至 Amazon 上的 EC2 设置 EC2 实例。如果您还没有,请快速阅读 AWS EC2。为 amzn-ami-hvm-2018.03.0.20180811-x86_64-gp2 或类似的东西(即最新的)设置一个。

    获取您的 EC2 .pem 文件。转到您的终端。 cd 进入 .pem 文件所在的文件夹。使用

    SSH 进入您的实例

    ssh -i "your-file-name-here.pem" ec2-user@ec2-ip-address-here.compute-1.amazonaws.com

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

    在您的 EC2 实例上,cd 进入 google-cloud-vision。运行命令:

    pip install google-cloud-vision -t .

注意如果出现“bash: pip: command not found”,则输入“sudo easy_install pip”source。

    使用以下软件包重复第 4 步,同时 cd'ing 到相应的文件夹:protobuf、google-api-python-client、httplib2、uritemplate、google-auth-httplib2。

    复制计算机上的每个文件夹。您可以使用 scp 命令执行此操作。同样,在您的终端中,而不是您的 EC2 实例,而不是您用于访问 EC2 实例的终端窗口中,运行命令(以下是您的“google-cloud-vision”文件夹的示例,但对每个文件夹重复此操作):

    sudo scp -r -i your-pem-file-name.pem ec2-user@ec2-ip-address-here.compute-1.amazonaws.com:~/google-cloud-vision ~/Documents/your -本地目录/

    从 AWS 控制台停止您的 EC2 实例,以免被多收费用。

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

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

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

    最后,将您的 Python 脚本放入此文件夹,压缩 内容(不是文件夹),上传到 S3,然后将链接粘贴到您的 AWS Lambda 函数中,然后开始吧!

如果此处的某些内容与描述的不符,请原谅我并给我发消息或随时编辑我的答案。希望这会有所帮助。

【讨论】:

谢谢!很长一段时间以来一直试图解决这个问题,这很有效! @Nour 没问题,我很乐意提供帮助!【参考方案2】:

基于@Josh Wolff 的答案(非常感谢,顺便说一句!),这可以通过使用 Amazon 提供的 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 ;

以上脚本将:

    如果您还没有 Docker 映像,请拉取它(以上使用 Python 3.6) 删除python目录(仅对运行第二个有用 时间) 将所有需求安装到 python 目录,在您的项目 /src 目录中创建 压缩python目录 上传 AWS 层 删除python目录和zip文件

确保您的 requirements.txt 文件包含 Josh 上面列出的模块:google-cloud-vision、protobuf、google-api-python-client、httplib2、uritemplate、google-auth-httplib2

【讨论】:

感谢您的贡献!【参考方案3】:

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

Cloud9 使用 AMI,因此在他们的虚拟环境中使用 pip 应该可以正常工作。

我从 Cloud9 UI 创建了一个 Lambda,并从控制台激活了 EC2 机器的 venv。我继续使用 pip 安装 google-cloud-speech。这足以解决问题。

【讨论】:

【参考方案4】:

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

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

我的 Lambda 运行时是 Python 3.9 和架构 x86_64。

如果有人遇到类似的 ImportModuleError,请在此处查看我的答案:Cannot import name 'cygrpc' from 'grpc._cython' - Google Ads API

【讨论】:

以上是关于适用于 Python 和 AWS Lambda 的 Google Cloud Platform API 不兼容:无法导入名称“cygrpc”的主要内容,如果未能解决你的问题,请参考以下文章

适用于 AWS Lambda 的本地开发服务器

Twilio API 调用适用于本地环境,但不适用于 AWS Lambda 函数

AWS Lambda (Python) 无法在 S3 中解压缩和存储文件

如何为 pymysql lambda 启用 AWS XRAY 跟踪

为 Scikit-image 构建自定义 AWS Lambda 层

Python 脚本作为 AWS S3 存储桶上的 Cron