AWS Lambda:无法导入模块 'python_handler':没有名为“_cffi_backend”的模块
AWS Lambda: Unable to import module 'python_handler': No module named '_cffi_backend'
当我需要读取 API 上的信息、创建 CSV 文件并将它们上传到 SFTP 服务器时,我正在创建 AWS Lambda 函数。
我在我的 venv 上安装了 paramiko,在 Windows 上使用 Ubuntu,cffi 模块就像一个依赖项一样出现,但是当代码运行时,我收到这个错误:
{
"errorMessage": "Unable to import module 'python_handler': No module named '_cffi_backend'",
"errorType": "Runtime.ImportModuleError"
}
按照我的代码:
import paramiko
import requests
from random import randrange
from datetime import datetime
from datetime import timedelta
from requests.auth import HTTPBasicAuth
def lambda_handler(event, context):
# Lambda function
addZero = lambda x : '0' + str(x) if x < 10 else str(x)
# Actual datetime
ac_yr = datetime.utcnow().year
ac_mo = datetime.utcnow().month
ac_da = datetime.utcnow().day
ac_hh = datetime.utcnow().hour
ac_mi = datetime.utcnow().minute
ac_se = datetime.utcnow().second
# 24 hours ago
ag_yr = (datetime.utcnow() - timedelta(hours=24)).year
ag_mo = (datetime.utcnow() - timedelta(hours=24)).month
ag_da = (datetime.utcnow() - timedelta(hours=24)).day
ag_hh = (datetime.utcnow() - timedelta(hours=24)).hour
ag_mi = (datetime.utcnow() - timedelta(hours=24)).minute
ag_se = (datetime.utcnow() - timedelta(hours=24)).second
# API Infos
api_key = 'XYZ'
page_id = 'XYZ'
# Call API
param = {
'sort_order': 'asc',
'from': '{}-{}-{}T{}:{}:{}.000Z'.format(ag_yr, addZero(ag_mo), addZero(ag_da), addZero(ag_hh), addZero(ag_mi), addZero(ag_se)),
'to': '{}-{}-{}T{}:{}:{}.000Z'.format(ac_yr, addZero(ac_mo), addZero(ac_da), addZero(ac_hh), addZero(ac_mi), addZero(ac_se))
}
r = requests.get('https://api.unbounce.com/pages/{}/leads'.format(page_id), auth=HTTPBasicAuth(api_key, 'pass'), params=param)
# If connection it's ok
if r.status_code == 200:
# If has any result
if len(r.json()['leads']) > 0:
cont = ''
for lead in r.json()['leads']:
cont += lead['form_data']['cpf'][0] + ','
cont += lead['form_data']['nome_completo'][0] + ','
cont += lead['form_data']['email'][0]
else:
return 'Não há resultados no momento'
else:
return 'Falha na conexão'
# Write a CSV file
f = open('my_csv.csv','w')
f.write('PAC_ID, PAC_NAME, PAC_EMAIL\n')
f.write(cont)
f.close()
transport = paramiko.Transport(('host-info', 22))
transport.connect(None, 'user-info', 'password-info', None)
sftp = paramiko.SFTPClient.from_transport(transport)
sftp.chdir('Import')
sftpclient.put('my_csv.csv')
return 'OK'
知道如何解决这个问题吗?
这看起来像是许多二进制包的常见问题。
我还没有一个通用的解决方案,但你真正需要做的是将二进制文件从它真正安装的地方移动(符号链接)到你的包的根目录。
我通常使用 post 为我的 Lambda 安装脚本来解决这个问题。那些使用 paramiko
运行 的是:
ln -s venv/MY_LAMBDA/lib/python3.6/site-packages/_cffi_backend.cpython-36m-x86_64-linux-gnu.so MY_LAMBDA/
ln -s venv/MY_LAMBDA/lib/python3.6/site-packages/.libs_cffi_backend/libffi-XXXXXXXX.so.6.0.4 MY_LAMBDA/
ln -s venv/MY_LAMBDA/lib/python3.6/site-packages/nacl MY_LAMBDA/
您必须从您的 virtualenv 中确定 libffi...
文件的确切名称。它可能与您编译库的机器不同。
在 Ubuntu 上工作,我没有成功地将 pysftp 或 paramiko 连接到 Lambda。
因此,我在我的桌面上创建了一个 EC2 实例(以及在 VirtualBox with Amazon Linux 2 之后)并使用相同的库开发相同的代码。而且...这很有效...
可能会迟到,希望以后能对某人有所帮助。此答案特定于“_cffi_backend.....”。另一件可能有帮助的事情是了解您是如何安装的 python。如果使用 brew,您将需要使用 python 创建一个虚拟环境。看这里:
https://docs.aws.amazon.com/lambda/latest/dg/lambda-python-how-to-create-deployment-package.html
我在 linux 环境中完成了此操作,而没有下载与各种 linux 发行版兼容的 wheel 文件并且它有效
最简单的解决方案是使用 lambci/lambda container as described here. I wrote about it in some detail here.
简而言之,一些 Python 包(例如 cffi
)具有 OS 级别的依赖性。由于 OS 您打包代码的方式与 Lambda 使用的不同,因此脚本无法 运行.
当我需要读取 API 上的信息、创建 CSV 文件并将它们上传到 SFTP 服务器时,我正在创建 AWS Lambda 函数。
我在我的 venv 上安装了 paramiko,在 Windows 上使用 Ubuntu,cffi 模块就像一个依赖项一样出现,但是当代码运行时,我收到这个错误:
{
"errorMessage": "Unable to import module 'python_handler': No module named '_cffi_backend'",
"errorType": "Runtime.ImportModuleError"
}
按照我的代码:
import paramiko
import requests
from random import randrange
from datetime import datetime
from datetime import timedelta
from requests.auth import HTTPBasicAuth
def lambda_handler(event, context):
# Lambda function
addZero = lambda x : '0' + str(x) if x < 10 else str(x)
# Actual datetime
ac_yr = datetime.utcnow().year
ac_mo = datetime.utcnow().month
ac_da = datetime.utcnow().day
ac_hh = datetime.utcnow().hour
ac_mi = datetime.utcnow().minute
ac_se = datetime.utcnow().second
# 24 hours ago
ag_yr = (datetime.utcnow() - timedelta(hours=24)).year
ag_mo = (datetime.utcnow() - timedelta(hours=24)).month
ag_da = (datetime.utcnow() - timedelta(hours=24)).day
ag_hh = (datetime.utcnow() - timedelta(hours=24)).hour
ag_mi = (datetime.utcnow() - timedelta(hours=24)).minute
ag_se = (datetime.utcnow() - timedelta(hours=24)).second
# API Infos
api_key = 'XYZ'
page_id = 'XYZ'
# Call API
param = {
'sort_order': 'asc',
'from': '{}-{}-{}T{}:{}:{}.000Z'.format(ag_yr, addZero(ag_mo), addZero(ag_da), addZero(ag_hh), addZero(ag_mi), addZero(ag_se)),
'to': '{}-{}-{}T{}:{}:{}.000Z'.format(ac_yr, addZero(ac_mo), addZero(ac_da), addZero(ac_hh), addZero(ac_mi), addZero(ac_se))
}
r = requests.get('https://api.unbounce.com/pages/{}/leads'.format(page_id), auth=HTTPBasicAuth(api_key, 'pass'), params=param)
# If connection it's ok
if r.status_code == 200:
# If has any result
if len(r.json()['leads']) > 0:
cont = ''
for lead in r.json()['leads']:
cont += lead['form_data']['cpf'][0] + ','
cont += lead['form_data']['nome_completo'][0] + ','
cont += lead['form_data']['email'][0]
else:
return 'Não há resultados no momento'
else:
return 'Falha na conexão'
# Write a CSV file
f = open('my_csv.csv','w')
f.write('PAC_ID, PAC_NAME, PAC_EMAIL\n')
f.write(cont)
f.close()
transport = paramiko.Transport(('host-info', 22))
transport.connect(None, 'user-info', 'password-info', None)
sftp = paramiko.SFTPClient.from_transport(transport)
sftp.chdir('Import')
sftpclient.put('my_csv.csv')
return 'OK'
知道如何解决这个问题吗?
这看起来像是许多二进制包的常见问题。 我还没有一个通用的解决方案,但你真正需要做的是将二进制文件从它真正安装的地方移动(符号链接)到你的包的根目录。
我通常使用 post 为我的 Lambda 安装脚本来解决这个问题。那些使用 paramiko
运行 的是:
ln -s venv/MY_LAMBDA/lib/python3.6/site-packages/_cffi_backend.cpython-36m-x86_64-linux-gnu.so MY_LAMBDA/
ln -s venv/MY_LAMBDA/lib/python3.6/site-packages/.libs_cffi_backend/libffi-XXXXXXXX.so.6.0.4 MY_LAMBDA/
ln -s venv/MY_LAMBDA/lib/python3.6/site-packages/nacl MY_LAMBDA/
您必须从您的 virtualenv 中确定 libffi...
文件的确切名称。它可能与您编译库的机器不同。
在 Ubuntu 上工作,我没有成功地将 pysftp 或 paramiko 连接到 Lambda。 因此,我在我的桌面上创建了一个 EC2 实例(以及在 VirtualBox with Amazon Linux 2 之后)并使用相同的库开发相同的代码。而且...这很有效...
可能会迟到,希望以后能对某人有所帮助。此答案特定于“_cffi_backend.....”。另一件可能有帮助的事情是了解您是如何安装的 python。如果使用 brew,您将需要使用 python 创建一个虚拟环境。看这里:
https://docs.aws.amazon.com/lambda/latest/dg/lambda-python-how-to-create-deployment-package.html
我在 linux 环境中完成了此操作,而没有下载与各种 linux 发行版兼容的 wheel 文件并且它有效
最简单的解决方案是使用 lambci/lambda container as described here. I wrote about it in some detail here.
简而言之,一些 Python 包(例如 cffi
)具有 OS 级别的依赖性。由于 OS 您打包代码的方式与 Lambda 使用的不同,因此脚本无法 运行.