【问题标题】:How can I solve cx_Oracle problem in python when running on aws lambda在 aws lambda 上运行时如何解决 python 中的 cx_Oracle 问题
【发布时间】:2019-02-15 12:14:41
【问题描述】:

我在 aws lambda 上测试时遇到以下错误消息。

Unable to import module 'lambda_handler': No module named 'cx_Oracle'

这个 lambda 由 python 代码组成,但特别适用于我的本地主机。

另外,我在同一级别的 lambda_handler.py 文件路径上执行了pip install cx_Oracle -t ./ 命令,上传的 zip 文件的文件路径低于该路径。

./lambda_handler.py

./cx_Oracle.cp36-win_amd64.pyd

./cx_Oracle-6.4.1.dist-info/*

./cx_Oracle-doc/*

我不明白为什么 lambda_handler 只能在 lambda 函数中找到 cx_Oracle library

我错过了什么?

import cx_Oracle
import boto3
from docutils.nodes import row

def lambda_handler(event, context):

    url = 'myOracleUrl'
    user = 'myOralceUserId'
    pwd = 'myOraclePwd'
    con = cx_Oracle.connect(user + '/' + pwd + '@' + url)
    cur = con.cursor()
    cur.execute("select 1 from dual")
    cur.close()
    con.close()

    return {
        "statusCode": 200,
        "body": context.invoked_function_arn
    }

【问题讨论】:

  • 不要忘记 Oracle Instant Client 和匹配的 VS Redistributable。这可能无法解决眼前的问题,因为我预计会出现不同的错误消息。

标签: python amazon-web-services aws-lambda cx-oracle


【解决方案1】:

简答
您使用的 cx_Oracle 库适用于 Windows。 Aws Lambda 环境是Amazon Linux,*.pyd 是适用于 Windows 的 Python 库。

长答案: 你必须部署linux版本 您弄错的第一件事是您将代码连同您的代码一起提供给 AWS Lambda 的 python 库。我猜你是在 Windows 机器上进行本地开发,所以当你这样做时:

pip install cx_Oracle -t ./

你会得到一个用于 Windows 的 python 预编译库,它是 cx_Oracle.cp36-win_amd64.pyd 文件。 AWS Lambda 在 Linux 容器中运行。你可以找到一些关于环境的信息here。 Linux 的预编译库是 cx_Oracle.cpython-36m-x86_64-linux-gnu.so。您可以从Pypi repository手动下载。

所以当你在 Linux 环境中执行 python 脚本时,它会尝试在当前路径中找到库的 linux 预编译版本,cx_Oracle.cpython-36m-x86_64-linux-gnu.so强>文件。这就是您收到错误消息的原因:

Unable to import module 'lambda_handler': No module named 'cx_Oracle'

这里重要的第二件事是 cx_Oracle python 库调用 Oracle Instant Client 这是一个本地库。如果你的 Windows 机器上有一个工作示例,你必须安装它。对于 Windows,这个库是 .dll 文件的形式。对于 linux,这个本地库是 .so 文件的形式。 您需要在部署包中提供 适用于 Linux 的 Oracle 客户端以及您的代码,因为在 Amazon Linux 环境中尚不可用。

最后一件事是告诉 Python 如何找到这个动态库。在 Linux 系统中,在此环境变量 LD_LIBRARY_PATH 中存在的目录中查找共享库。在 Amazon Linux 中,此变量包含:

LD_LIBRARY_PATH:/var/lang/lib:/lib64:/usr/lib64:/var/runtime:/var/runtime/lib:/var/task:/var/task/lib:/opt/lib

/var/task 目录是您的部署所在的位置。因此,如果您在开发目录中的/var/task/lib(即./lib)下添加适用于 Linux 的 Oracle 即时客户端,您就完成了。

你的部署包应该是这样的:

├── lib                         
│   ├── libclntsh.so                            <-- Oracle instant client linux files
│            .
│            .
│            .
├── python_handler.py                           <-- Lambda function code
└── cx_Oracle.cpython-36m-x86_64-linux-gnu.so   <-- cx_Oracle library

【讨论】:

  • 关于 Oracle 即时客户端 linux 文件...从 Oracle 下载的是 227MB。我应该将哪些文件放在“lib”文件夹中?
  • 您只需要包含 libclntsh.so,这是 cx_Oracle python 库将调用的二进制依赖项
  • 根据我的经验,不要在 Windows 中这样做。在 Linux 中进行。不要获取 zip 文件,而是使用 RPM 进行安装。获取基本版本。基本的压缩包将超过 50MB 的 lambda 限制。您必须在 /usr/lib/oracle/.../lib 中添加 /lib64/libaio* 文件。放松对lib文件夹中文件的权限,然后将它们压缩起来 - zip --symlinks -r9 ~/lamda.zip *
【解决方案2】:

cx_Oracle 不仅需要pip install,还需要车轮所依赖的本机 Oracle 客户端。 Lambda 函数在 EC2 上运行,具有有限的本地库选择。对于它的价值,几乎任何 RDBMS(PostgreSQL、MySQL 等)都会遇到同样的问题。

查看这篇文章了解更多信息:http://kb.sites.apiit.edu.my/knowledge-base/articles/aws/aws-chalice-deployment-with-oracle-vendor/

请注意,这是基于 Chalice 的部署,但基本要求是相同的。

【讨论】:

    【解决方案3】:

    我们遇到了这个确切的问题,然后我们不得不在 AWS Lambda Java 8 而不是 Python 3.6 中实现数据访问函数

    在 Java 8 中,ojdbc*.jar(* --> Oracle 驱动程序的版本号)可以简单地捆绑到最终的 zip 中,并且没有其他步骤,例如尝试获取 Oracle 客户端本地库。

    我们确实花了很多时间让 AWS Lambda Python 函数访问 Oracle DB,但我觉得在 AWS Lambda Java 8 函数中开发此类模块要简单得多

    【讨论】:

    • 非常感谢,我通过在 zip 文件中包含 oracle 实例客户端解决了这个问题。但它比使用 java 花费的时间更多。
    猜你喜欢
    • 2019-09-28
    • 2020-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-10
    • 2019-07-02
    • 1970-01-01
    • 2020-02-21
    相关资源
    最近更新 更多