在 Python 中将 MySQL 与 AWS Lambda 结合使用时出现问题
Problems using MySQL with AWS Lambda in Python
我正在尝试起床 运行 AWS Lambda Python(Python 顺便说一句,初学者)但是在包含 MySQL 依赖项时遇到了一些问题。我正在尝试按照 Mac.
上的说明进行操作 here
对于第 3 步,我在项目的根目录执行命令时遇到了一些问题
sudo pip install MySQL-python -t /
错误:
Exception:
Traceback (most recent call last):
File "/Library/Python/2.7/site-packages/pip-1.5.6-py2.7.egg/pip/basecommand.py", line 122, in main
status = self.run(options, args)
File "/Library/Python/2.7/site-packages/pip-1.5.6-py2.7.egg/pip/commands/install.py", line 311, in run
os.path.join(options.target_dir, item)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/shutil.py", line 292, in move
raise Error, "Destination path '%s' already exists" % real_dst
Error: Destination path '/MySQL_python-1.2.5-py2.7.egg-info/MySQL_python-1.2.5-py2.7.egg-info' already exists
我最终编写了以下 lambda 函数(在我的 Mac 上运行良好),即:
import MySQLdb
def lambda_handler(event, context):
# Open database connection
db = MySQLdb.connect(...)
# prepare a cursor object using cursor() method
cursor = db.cursor()
sql = "SELECT * FROM Users"
try:
# Execute the SQL command
cursor.execute(sql)
# Fetch all the rows in a list of lists.
results = cursor.fetchall()
for row in results:
fname = row[0]
lname = row[1]
age = row[2]
sex = row[3]
income = row[4]
# Now print fetched result
print ("lname=%s" %(lname))
except:
print "Error: unable to fecth data"
# disconnect from server
db.close()
我接下来要做的是转到 /Library/Python/2.7/site-packages 并复制我执行 sudo pip install 时下载的 MySQLdb folders/files MySQL-python(没有 -t /)(我确定我在这里做错了什么)到我的 lambda 项目,然后将内容与 lambda_function.py 和上传到 AWS Lambda。
然后我得到:
Unable to import module 'lambda_function': No module named MySQLdb
感谢任何帮助和建议!
编辑
能够做到 make sudo pip install MySQL-python -t /pathToProject 工作(感谢评论中的帮助)但现在我在运行 lambda 函数时得到了这个:
Unable to import module 'lambda_function': /var/task/_mysql.so: invalid ELF header
我知道如果我在 Linux 盒子上工作,那么它应该可以正常工作(正如某些人所建议的那样),但我想知道我是否可以在 OS 上工作X盒.
我认为您的问题主要是因为缺少开发包。我认为您将需要以下内容:
sudo yum -y 安装mysql-devel
问题在我的 Ubuntu 安装程序中发生类似,真正的问题是因为它在 mysql 客户端连接器驱动程序上挂起。所以解决方案是安装 Mysql client-dev 包以使 MySQL-python 快乐(使用客户端库)。
# Ubuntu only(or setup vm for ubuntu inside your mac)
# Three dependencies for MySQL python recompilation
sudo apt-get install python-dev libssl-dev
#Now the mysql client-dev
sudo apt-get install libmysqlclient-dev
# If you like mariadb client
sudo apt-get install libmariadbclient-dev
对于MAC
# try this first
fink install mysql-unified-dev
# or this if above fail.
brew install mysql
# you must add this to your user profile startup if you use brew
export PATH=$PATH:/usr/local/mysql/bin
你可以在这里得到类似的答案:Mac OS X - EnvironmentError: mysql_config not found
然后尝试 pip 安装。
我不建议任何人使用 "sudo pip"。你应该为你的 python 开发设置 Virtualenv 和 virtualwrapper,这样你就可以在没有 sudo 的情况下进行 pip。而且更容易隔离和测试新的部署。 (虽然它没有解决 mysqlclient-dev 库问题)
您必须使用 Amazon Linux 实例来构建您的 python 程序包,然后将它们包含在您的 Lambda 部署程序包中。查看 this excellent article 了解如何操作。文章中提到的软件包与您需要的不同,但同样它帮助我为我的 lambda 构建了 psycopg2 和 pymssql。
对于像 Lambda 这样的用例,使用像 PyMySQL 这样的纯 python 实现会更快乐。
这是对遵循 Python Database API 规范的 MySQLdb 的替代品。对于大多数事情,例如触发的 Lambda 事件,它会一样快。
我在生产中经常使用它,效果很好。
使用 lambda-docker,您可以设置和测试您的 Lambda 函数,而无需访问类似的 Linux 环境。
要设置您的 lambda,请将 lambda-docker 构建映像用于 运行 分离的 docker 容器,并在容器上使用 运行 pip install <package>
命令。然后导出容器,抓取 usr/lib
下安装的包,并将它们放入您的 AWS Lambda 包中。
然后您可以通过在 lambda-docker 图像上 运行ning 您的 lambda 来测试兼容性。如果有效,请放心上传到 AWS Lambda。
docker run -d -v "$PWD":/var/task lambci/lambda:build-python2.7 tail -f /dev/null
docker ps
docker exec 0c55aae443e6 pip install pandas
docker exec 0c55aae443e6 pip install sqlalchemy
docker exec 0c55aae443e6 pip freeze
docker exec 0c55aae443e6 python -c "import site; print(site.getsitepackages())"
docker container export -o lambda_ready_container 0c55aae443e6
只需上传两个包来更新您的 lambda 层:
- sqlalchemy
- PyMySQL(代替 mysqlclient 使用的驱动程序)
现在将您的驱动程序 url 更新为 "mysql+pymysql://..."。
这使您可以为现有环境使用与 Lambda 环境兼容的 pymysql 驱动程序。
不要忘记为 RDS 设置 VPC 端点。这样可以控制性能和安全性。
AWS 最近针对 Lambda 中的数据库驱动程序和数据库访问问题提出了一个很好的解决方案:Aurora Data API。数据 API 使用 AWS 标准身份验证通过 HTTP 隧道 SQL。这绕过了在 Lambda 中编译本机代码和使用传统数据库连接模型的问题。
我最终为它编写了一个 DB-API 兼容驱动程序:aurora-data-api (and a SQLAlchemy dialect 使用它):
import aurora_data_api
cluster_arn = "arn:aws:rds:us-east-1:123456789012:cluster:my-aurora-serverless-cluster"
secret_arn = "arn:aws:secretsmanager:us-east-1:123456789012:secret:MY_DB_CREDENTIALS"
with aurora_data_api.connect(aurora_cluster_arn=cluster_arn, secret_arn=secret_arn, database="my_db") as conn:
with conn.cursor() as cursor:
cursor.execute("select * from pg_catalog.pg_tables")
print(cursor.fetchall())
Lambda -> Layers(添加新层)
从 https://pypi.org/project/PyMySQL/#files
下载 pymysql 的 zip
当你下载时,解压缩然后将父文件夹重命名为 "python" 然后重新压缩(应该是 python/{pysql 文件所在的位置}
向 Lambda 添加一个名为 'pymysql' 的层并上传该 zip
然后在 Lambda 函数中导入 pymysql
TLDR:是的,您可以在 AWS Lambda Python 函数中使用 mysqlclient
。
这是一种方法 - 通过为 mysqlclient
(即 MySQLdb
)创建您自己的 AWS Lambda 层。
Then I get Unable to import module 'lambda_function': No module named MySQLdb
I know that if I work on a Linux box, then it should work fine (as suggested by some people), but I am wondering if I can make it work from an OS X box.
我在我的 AWS Lambda Python 函数中尝试 import MySQLdb
时也遇到了完全相同的错误。
经过大量搜索解决方案并且不满意使用 pymysql
作为替代品(出于性能和兼容性原因),我最终构建了自己的 AWS Lambda Layer for mysqlclient
. I could not find a "ready-made" layer for mysqlclient
- not even at the awesome KLayers project。我很高兴分享一个 GitHub 存储库,其中包含一个“现成”层示例和一个简单的解决方案,可以根据您的要求使用 AWS 推荐的程序构建您自己的自定义层。
mysqlclient
(MySQLdb) is a Python wrapper around a high-performance C implementation of the MySQL API. This makes it typically much faster than pure-python implementations such as pymysql
in most cases (see this list 一些例子),但它也带来了一些问题,例如你所面临的问题。
因为它是针对 mysql-devel
包编译的(例如 MySQL 提供的 .rpm
或 .deb
文件),mysqlclient
链接到特定于平台的二进制文件,例如 libmysqlclient.so
才能工作。换句话说,来自 Mac OS 笔记本电脑(作为示例)的 libmysqlclient.so
将无法在使用某种形式的 Amazon Linux 2
的 AWS Lambda 环境中工作写作。您需要 libmysqlclient.so
在 AWS Lambda 环境中(或尽可能接近它)编译,才能在您的 AWS Lambda 函数中运行。
的形式提供了一个紧密模拟的 AWS-Lambda 环境
因此,要打包兼容 AWS-Lambda 的 mysqlclient
,您可以:
- 拉一个合适的docker容器比如
lambci/lambda:build-python3.8
- 导入 MySQL repo GPG key
- 安装 MySQL repo setup RPM 以便
yum
可以找到并下载其他 MySQL 回购包
yum install
必要的依赖项,例如适合您的用例的 mysql-devel
rpm
- 运行
pip install mysqlclient
容器中
- 压缩必要的
libmysqlclient.so
文件和 mysqlclient 的 python lib 目录
这或多或少是 AWS 官方推荐的程序:请参阅 如何使用带有 Docker 的模拟 Lambda 环境创建 Lambda 层?
.
由此创建的 zip 可用于为 mysqlclient
创建一个新的 AWS Lambda 层。您可以使用此层轻松使用 mysqlclient
,而不会在您的 Lambda 函数中出现任何错误。
经过大量的努力,我终于得到了完整的工作过程,并将其自动化到 this GitHub project 中的单个脚本 (build.sh
) 中。该代码构建了一个 layer.zip
文件,您可以将其作为新的 AWS Lambda 层直接上传。该项目当前为 Python3.8 和 MySQL 服务器 8.0.x 构建,但可以轻松适应不同的 Python 版本和目标 MySQL 版本,使用提供的说明和工具。回购协议中还有一个随时可用的 layer.zip
- 如果您想对 MySQL v8.0.x 和 Python 3.8 使用 mysqlclient
(均经过测试)在您的 AWS Lambda 函数中。我们的生产环境使用 SqlAlchemy,它使用这个 MySqlClient Lambda 层,它对我们来说效果很好。
将 Lambda 函数配置为使用按描述构建的层(例如,使用上述存储库中的工具)后,您可以像往常一样在 Lambda 函数中 import MySQLdb
并继续编写您真正的代码:
import MySQLdb
def lambda_handler(event, context):
return {
'statusCode': 200,
'body': 'MySQLdb was successfully imported'
}
希望对您有所帮助。
我正在尝试起床 运行 AWS Lambda Python(Python 顺便说一句,初学者)但是在包含 MySQL 依赖项时遇到了一些问题。我正在尝试按照 Mac.
上的说明进行操作 here对于第 3 步,我在项目的根目录执行命令时遇到了一些问题
sudo pip install MySQL-python -t /
错误:
Exception: Traceback (most recent call last): File "/Library/Python/2.7/site-packages/pip-1.5.6-py2.7.egg/pip/basecommand.py", line 122, in main status = self.run(options, args) File "/Library/Python/2.7/site-packages/pip-1.5.6-py2.7.egg/pip/commands/install.py", line 311, in run os.path.join(options.target_dir, item) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/shutil.py", line 292, in move raise Error, "Destination path '%s' already exists" % real_dst Error: Destination path '/MySQL_python-1.2.5-py2.7.egg-info/MySQL_python-1.2.5-py2.7.egg-info' already exists
我最终编写了以下 lambda 函数(在我的 Mac 上运行良好),即:
import MySQLdb
def lambda_handler(event, context):
# Open database connection
db = MySQLdb.connect(...)
# prepare a cursor object using cursor() method
cursor = db.cursor()
sql = "SELECT * FROM Users"
try:
# Execute the SQL command
cursor.execute(sql)
# Fetch all the rows in a list of lists.
results = cursor.fetchall()
for row in results:
fname = row[0]
lname = row[1]
age = row[2]
sex = row[3]
income = row[4]
# Now print fetched result
print ("lname=%s" %(lname))
except:
print "Error: unable to fecth data"
# disconnect from server
db.close()
我接下来要做的是转到 /Library/Python/2.7/site-packages 并复制我执行 sudo pip install 时下载的 MySQLdb folders/files MySQL-python(没有 -t /)(我确定我在这里做错了什么)到我的 lambda 项目,然后将内容与 lambda_function.py 和上传到 AWS Lambda。
然后我得到:
Unable to import module 'lambda_function': No module named MySQLdb
感谢任何帮助和建议!
编辑
能够做到 make sudo pip install MySQL-python -t /pathToProject 工作(感谢评论中的帮助)但现在我在运行 lambda 函数时得到了这个:
Unable to import module 'lambda_function': /var/task/_mysql.so: invalid ELF header
我知道如果我在 Linux 盒子上工作,那么它应该可以正常工作(正如某些人所建议的那样),但我想知道我是否可以在 OS 上工作X盒.
我认为您的问题主要是因为缺少开发包。我认为您将需要以下内容:
sudo yum -y 安装mysql-devel
问题在我的 Ubuntu 安装程序中发生类似,真正的问题是因为它在 mysql 客户端连接器驱动程序上挂起。所以解决方案是安装 Mysql client-dev 包以使 MySQL-python 快乐(使用客户端库)。
# Ubuntu only(or setup vm for ubuntu inside your mac)
# Three dependencies for MySQL python recompilation
sudo apt-get install python-dev libssl-dev
#Now the mysql client-dev
sudo apt-get install libmysqlclient-dev
# If you like mariadb client
sudo apt-get install libmariadbclient-dev
对于MAC
# try this first
fink install mysql-unified-dev
# or this if above fail.
brew install mysql
# you must add this to your user profile startup if you use brew
export PATH=$PATH:/usr/local/mysql/bin
你可以在这里得到类似的答案:Mac OS X - EnvironmentError: mysql_config not found
然后尝试 pip 安装。
我不建议任何人使用 "sudo pip"。你应该为你的 python 开发设置 Virtualenv 和 virtualwrapper,这样你就可以在没有 sudo 的情况下进行 pip。而且更容易隔离和测试新的部署。 (虽然它没有解决 mysqlclient-dev 库问题)
您必须使用 Amazon Linux 实例来构建您的 python 程序包,然后将它们包含在您的 Lambda 部署程序包中。查看 this excellent article 了解如何操作。文章中提到的软件包与您需要的不同,但同样它帮助我为我的 lambda 构建了 psycopg2 和 pymssql。
对于像 Lambda 这样的用例,使用像 PyMySQL 这样的纯 python 实现会更快乐。
这是对遵循 Python Database API 规范的 MySQLdb 的替代品。对于大多数事情,例如触发的 Lambda 事件,它会一样快。
我在生产中经常使用它,效果很好。
使用 lambda-docker,您可以设置和测试您的 Lambda 函数,而无需访问类似的 Linux 环境。
要设置您的 lambda,请将 lambda-docker 构建映像用于 运行 分离的 docker 容器,并在容器上使用 运行 pip install <package>
命令。然后导出容器,抓取 usr/lib
下安装的包,并将它们放入您的 AWS Lambda 包中。
然后您可以通过在 lambda-docker 图像上 运行ning 您的 lambda 来测试兼容性。如果有效,请放心上传到 AWS Lambda。
docker run -d -v "$PWD":/var/task lambci/lambda:build-python2.7 tail -f /dev/null
docker ps
docker exec 0c55aae443e6 pip install pandas
docker exec 0c55aae443e6 pip install sqlalchemy
docker exec 0c55aae443e6 pip freeze
docker exec 0c55aae443e6 python -c "import site; print(site.getsitepackages())"
docker container export -o lambda_ready_container 0c55aae443e6
只需上传两个包来更新您的 lambda 层: - sqlalchemy - PyMySQL(代替 mysqlclient 使用的驱动程序)
现在将您的驱动程序 url 更新为 "mysql+pymysql://..."。
这使您可以为现有环境使用与 Lambda 环境兼容的 pymysql 驱动程序。
不要忘记为 RDS 设置 VPC 端点。这样可以控制性能和安全性。
AWS 最近针对 Lambda 中的数据库驱动程序和数据库访问问题提出了一个很好的解决方案:Aurora Data API。数据 API 使用 AWS 标准身份验证通过 HTTP 隧道 SQL。这绕过了在 Lambda 中编译本机代码和使用传统数据库连接模型的问题。
我最终为它编写了一个 DB-API 兼容驱动程序:aurora-data-api (and a SQLAlchemy dialect 使用它):
import aurora_data_api
cluster_arn = "arn:aws:rds:us-east-1:123456789012:cluster:my-aurora-serverless-cluster"
secret_arn = "arn:aws:secretsmanager:us-east-1:123456789012:secret:MY_DB_CREDENTIALS"
with aurora_data_api.connect(aurora_cluster_arn=cluster_arn, secret_arn=secret_arn, database="my_db") as conn:
with conn.cursor() as cursor:
cursor.execute("select * from pg_catalog.pg_tables")
print(cursor.fetchall())
Lambda -> Layers(添加新层)
从 https://pypi.org/project/PyMySQL/#files
下载 pymysql 的 zip当你下载时,解压缩然后将父文件夹重命名为 "python" 然后重新压缩(应该是 python/{pysql 文件所在的位置}
向 Lambda 添加一个名为 'pymysql' 的层并上传该 zip
然后在 Lambda 函数中导入 pymysql
TLDR:是的,您可以在 AWS Lambda Python 函数中使用 mysqlclient
。
这是一种方法 - 通过为 mysqlclient
(即 MySQLdb
)创建您自己的 AWS Lambda 层。
Then I get
Unable to import module 'lambda_function': No module named MySQLdb
I know that if I work on a Linux box, then it should work fine (as suggested by some people), but I am wondering if I can make it work from an OS X box.
我在我的 AWS Lambda Python 函数中尝试 import MySQLdb
时也遇到了完全相同的错误。
经过大量搜索解决方案并且不满意使用 pymysql
作为替代品(出于性能和兼容性原因),我最终构建了自己的 AWS Lambda Layer for mysqlclient
. I could not find a "ready-made" layer for mysqlclient
- not even at the awesome KLayers project。我很高兴分享一个 GitHub 存储库,其中包含一个“现成”层示例和一个简单的解决方案,可以根据您的要求使用 AWS 推荐的程序构建您自己的自定义层。
mysqlclient
(MySQLdb) is a Python wrapper around a high-performance C implementation of the MySQL API. This makes it typically much faster than pure-python implementations such as pymysql
in most cases (see this list 一些例子),但它也带来了一些问题,例如你所面临的问题。
因为它是针对 mysql-devel
包编译的(例如 MySQL 提供的 .rpm
或 .deb
文件),mysqlclient
链接到特定于平台的二进制文件,例如 libmysqlclient.so
才能工作。换句话说,来自 Mac OS 笔记本电脑(作为示例)的 libmysqlclient.so
将无法在使用某种形式的 Amazon Linux 2
的 AWS Lambda 环境中工作写作。您需要 libmysqlclient.so
在 AWS Lambda 环境中(或尽可能接近它)编译,才能在您的 AWS Lambda 函数中运行。
因此,要打包兼容 AWS-Lambda 的 mysqlclient
,您可以:
- 拉一个合适的docker容器比如
lambci/lambda:build-python3.8
- 导入 MySQL repo GPG key
- 安装 MySQL repo setup RPM 以便
yum
可以找到并下载其他 MySQL 回购包 yum install
必要的依赖项,例如适合您的用例的mysql-devel
rpm- 运行
pip install mysqlclient
容器中 - 压缩必要的
libmysqlclient.so
文件和 mysqlclient 的 python lib 目录
这或多或少是 AWS 官方推荐的程序:请参阅 如何使用带有 Docker 的模拟 Lambda 环境创建 Lambda 层? .
由此创建的 zip 可用于为 mysqlclient
创建一个新的 AWS Lambda 层。您可以使用此层轻松使用 mysqlclient
,而不会在您的 Lambda 函数中出现任何错误。
经过大量的努力,我终于得到了完整的工作过程,并将其自动化到 this GitHub project 中的单个脚本 (build.sh
) 中。该代码构建了一个 layer.zip
文件,您可以将其作为新的 AWS Lambda 层直接上传。该项目当前为 Python3.8 和 MySQL 服务器 8.0.x 构建,但可以轻松适应不同的 Python 版本和目标 MySQL 版本,使用提供的说明和工具。回购协议中还有一个随时可用的 layer.zip
- 如果您想对 MySQL v8.0.x 和 Python 3.8 使用 mysqlclient
(均经过测试)在您的 AWS Lambda 函数中。我们的生产环境使用 SqlAlchemy,它使用这个 MySqlClient Lambda 层,它对我们来说效果很好。
将 Lambda 函数配置为使用按描述构建的层(例如,使用上述存储库中的工具)后,您可以像往常一样在 Lambda 函数中 import MySQLdb
并继续编写您真正的代码:
import MySQLdb
def lambda_handler(event, context):
return {
'statusCode': 200,
'body': 'MySQLdb was successfully imported'
}
希望对您有所帮助。