Python 从AWS Lambda连接Oracle

Python 从AWS Lambda连接Oracle,python,oracle,amazon-web-services,aws-lambda,Python,Oracle,Amazon Web Services,Aws Lambda,我有一个Lambda函数,需要使用pandas、sqlalchemy和cx_Oracle 将所有这些库安装和打包在一起超过了要求 我希望只包含的.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_

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

将所有这些库安装和打包在一起超过了要求

我希望只包含的.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:无法打开共享对象文件:没有这样的文件或目录”。求助 (此错误的背景信息位于:)

我也尝试过的

我试过:

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

  • os.system('export LD\u LIBRARY\u PATH=/tmp/instantclient\u 19\u 3')
    添加到python脚本中。与上述错误相同
  • 许多
    cp
    ln
    /tmp
    文件夹之外的Lambda中被禁止的东西。与上述错误相同
一种可行但不好的方法

如果我在Lambda包中创建一个名为
lib/
的文件夹,并包含一个奇怪的
libaio.so.1
libclntsh.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

解放党/
-李白奥,所以
-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.10.1
-libocci.so.11.1
-libocci.so.12.1
-libocci.so.18.1
-libocci.so.19.1
-利波西库斯
-利本斯
然而,我通过反复试验选择了这些文件,不想再重复一遍


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

我绝对不是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访问OS级API的权限非常有限。即使你这样做了,它也能以你不期望的方式表现出来。(假设:谁拥有“解压”功能?由该命令创建的文件将由谁可见/调用?)

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

我给你的唯一答案是

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

2/切勿尝试执行操作系统级调用。像os.system('export…')一样,始终使用完整路径

再看看您的问题,您指定环境变量的方式似乎有冲突

ORACLE_HOME: /tmp 
难道不是吗

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

另外,请参见:

您看过这个吗@Poojan它看起来像一个Python库,可以解压该文件,类似于我使用
os.system('unzip…')
。我没有问题解压缩文件,我有一个问题的cx_Oracle没有看到它。这是否解决了问题?您是否尝试在
解压oracle后
导入lib.reload(sa)
?因为它可能依赖于您更新的环境变量。此外,如果驱动程序安装正确,请尝试使用
sys.path
sys.modules
进行调试。可能
sys.path.insert(0,/tmp')
会有所帮助。另外,要更新当前的环境变量,请使用
os.environ['LD\u LIBRARY\u PATH']='/tmp/instantclient\u 19\u 3'
,因为
os.system('export…
不会更新当前python运行的环境。请检查
Environment: 
    Variables: 
      ORACLE_HOME: /tmp/instantclient_19_3
      LD_LIBRARY_PATH: /tmp/instantclient_19_3