【问题标题】:Connect Oracle from AWS Lambda从 AWS Lambda 连接 Oracle
【发布时间】:2020-08-15 21:34:22
【问题描述】:

我有一个需要使用 pandas、sqlalchemy 和 cx_Oracle 的 Lambda 函数。

将所有这些库安装和打包在一起超过了250MB deployment package limit of AWS Lambda

我想只包含Oracle Basic Light Package 的.zip,然后在运行时提取并使用它。

我的尝试

我的项目结构如下:

cx_Oracle-7.2.3.dist-info/
dateutil/
numpy/
pandas/
pytz/six-1.12.0.dist-info/
sqlalchemy/
SQLAlchemy-1.3.8.egg-info/
cx_Oracle.cpython-36m-x86_64-linux-hnu.so
instantclient-basiclite-linux.x64-19.3.0.0.0dbru.zip
main.py
six.py
template.yml

main.py 中,我运行以下命令:

import json, traceback, os

import sqlalchemy as sa
import pandas as pd

def main(event, context):
    try:
        unzip_oracle()
        return {'statusCode': 200,
                'body': json.dumps(run_query()),
                'headers': {'Content-Type': 'application/json', 'Access-Control-Allow-Origin':'*'}}
    except:
        em = traceback.format_exc()
        print("Error encountered. Error is: \n" + str(em))
        return {'statusCode': 500,
                'body': str(em),
                'headers': {'Content-Type': 'application/json', 'Access-Control-Allow-Origin':'*'}}  



def unzip_oracle():
    print('extracting oracle drivers and copying results to /var/task/lib')
    os.system('unzip /var/task/instantclient-basiclite-linux.x64-19.3.0.0.0dbru.zip -d /tmp')
    print('extraction steps complete')
    os.system('export ORACLE_HOME=/tmp/instantclient_19_3')


def get_db_connection():
    return sa.engine.url.URL('oracle+cx_oracle', 
        username='do_not_worry', password='about_any', 
        host='of_these', port=1521, 
        query=dict(service_name='details')
    )


def run_query():
    query_text = """SELECT * FROM dont_worry_about_it"""
    conn = sa.create_engine(get_db_connection())
    print('Connected')
    df = pd.read_sql(sa.text(query_text), conn)
    print(df.shape)
    return df.to_json(orient='records')

这会返回错误:

sqlalchemy.exc.DatabaseError:(cx_Oracle.DatabaseError) DPI-1047:找不到 64 位 Oracle 客户端库:“libclntsh.so:无法打开共享对象文件:没有这样的文件或目录”。请参阅https://oracle.github.io/odpi/doc/installation.html#linux 寻求帮助 (此错误的背景:http://sqlalche.me/e/4xp6

我也试过了

我试过了:

  • 添加
Environment: 
    Variables: 
      ORACLE_HOME: /tmp 
      LD_LIBRARY_PATH: /tmp 

template.yml 并重新部署。与上述相同的错误。

  • os.system('export LD_LIBRARY_PATH=/tmp/instantclient_19_3') 添加到python 脚本中。与上述相同的错误。
  • /tmp 文件夹之外的许多 cpln 在 Lambda 中被禁止。与上述相同的错误。

一种有效但不好的方法

如果我在 Lambda 包中创建一个名为 lib/ 的文件夹,并包含 libaio.so.1libclntsh.so 等奇怪的分类文件,出于某种原因,该函数将按预期工作强>。我最终得到了这个:

<all the other libraries and files as above>
lib/
-libaio.so.1
-libclntsh.so
-libclntsh.so.10.1
-libclntsh.so.11.1
-libclntsh.so.12.1
-libclntsh.so.18.1
-libclntsh.so.19.1
-libclntshcore.so.19.1
-libipc1.so
-libmql1.so
-libnnz19.so
-libocci.so
-libocci.so.10.1
-libocci.so.11.1
-libocci.so.12.1
-libocci.so.18.1
-libocci.so.19.1
-libociicus.so
-libons.so

但是,我通过反复试验选择了这些文件,不想再经历一次。

有没有办法在运行时在 Lambda 中解压缩 instantclient-basiclite-linux.x64-19.3.0.0.0dbru.zip,并让 Lambda 看到/使用它来连接到 Oracle 数据库?

【问题讨论】:

  • @Poojan 它看起来像一个可以解压缩文件的 Python 库,类似于我对 os.system('unzip ...') 所做的事情。我没有解压缩文件的问题,我有一个 cx_Oracle 看不到它的问题。这能解决问题吗?
  • 你有没有在unzip_oracle之后尝试importlib.reload(sa)?因为它可能会中继您更新的环境变量。此外,如果驱动程序安装正确,请尝试使用sys.pathsys.modules 进行调试。可能sys.path.insert(0, '/tmp') 可能会有所帮助。此外,要更新当前的环境变量,请使用os.environ['LD_LIBRARY_PATH'] = '/tmp/instantclient_19_3',因为os.system('export ... 不会更新当前 python 运行的环境。

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


【解决方案1】:

我绝对不是 python 专家,但这条线似乎很奇怪

print('extracting oracle drivers and copying results to /var/task/lib')
os.system('unzip /var/task/instantclient-basiclite-linux.x64-19.3.0.0.0dbru.zip -d /tmp')
print('extraction steps complete')
os.system('export ORACLE_HOME=/tmp/instantclient_19_3')

通常,您使用 Lambda 访问操作系统级 API 的权限非常有限。即使你这样做了,它也可以按照你不希望它做的方式行事。 (想一想:谁拥有“解压缩”功能?此命令创建的文件将由谁可见/可调用?)

我看到你提到你提取文件没有问题,这也有点奇怪

我给你的唯一答案是那个

1/ 尝试“自带”工具(解压缩等)

2/ 永远不要尝试进行操作系统级别的调用。像 os.system('export ...') ,总是使用完整路径

再看你的问题,好像你指定环境变量的方式有冲突

ORACLE_HOME: /tmp 

不应该

Environment: 
    Variables: 
      ORACLE_HOME: /tmp/instantclient_19_3
      LD_LIBRARY_PATH: /tmp/instantclient_19_3

另请参阅:How to access an AWS Lambda environment variable from Python

【讨论】:

    猜你喜欢
    • 2018-09-22
    • 2022-06-14
    • 1970-01-01
    • 2018-09-14
    • 2019-03-08
    • 2019-03-14
    • 1970-01-01
    • 2021-06-10
    • 2019-11-08
    相关资源
    最近更新 更多