从AWS Lambda连接Oracle

时间:2019-10-04 19:19:29

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

我有一个Lambda函数,需要使用熊猫,sqlalchemy和cx_Oracle。

将所有这些库一起安装和打包超过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脚本中。与上述相同。
  • cp文件夹外部的Lambda中禁止使用许多ln/tmp东西。与上述相同。

一种可行的方法,但很糟糕

如果我在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数据库?

1 个答案:

答案 0 :(得分: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来有限地访问OS级API。即使您这样做,它也可能会以您不希望它做的方式表现出来。 (想像一下:谁拥有“解压缩”功能?此命令创建的文件将对谁可见/可调用?)

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

我唯一给你的答案是

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

2 /永远不要尝试进行OS级调用。像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