python中的AWS Lambda导入模块错误
Posted
技术标签:
【中文标题】python中的AWS Lambda导入模块错误【英文标题】:AWS Lambda import module error in python 【发布时间】:2016-05-22 07:45:05 【问题描述】:我正在创建一个 AWS Lambda python 部署包。我正在使用一个外部依赖请求。我使用 AWS 文档 http://docs.aws.amazon.com/lambda/latest/dg/lambda-python-how-to-create-deployment-package.html 安装了外部依赖项。下面是我的python代码。
import requests
print('Loading function')
s3 = boto3.client('s3')
def lambda_handler(event, context):
#print("Received event: " + json.dumps(event, indent=2))
# Get the object from the event and show its content type
bucket = event['Records'][0]['s3']['bucket']['name']
key = urllib.unquote_plus(event['Records'][0]['s3']['object']['key']).decode('utf8')
try:
response = s3.get_object(Bucket=bucket, Key=key)
s3.download_file(bucket,key, '/tmp/data.txt')
lines = [line.rstrip('\n') for line in open('/tmp/data.txt')]
for line in lines:
col=line.split(',')
print(col[5],col[6])
print("CONTENT TYPE: " + response['ContentType'])
return response['ContentType']
except Exception as e:
print(e)
print('Error getting object from bucket . Make sure they exist and your bucket is in the same region as this function.'.format(key, bucket))
raise e
创建zip项目目录的内容并上传到lambda(压缩目录内容,而不是目录)。当我执行该功能时,我收到下面提到的错误。
START RequestId: 9e64e2c7-d0c3-11e5-b34e-75c7fb49d058 Version: $LATEST
**Unable to import module 'lambda_function': No module named lambda_function**
END RequestId: 9e64e2c7-d0c3-11e5-b34e-75c7fb49d058
REPORT RequestId: 9e64e2c7-d0c3-11e5-b34e-75c7fb49d058 Duration: 19.63 ms Billed Duration: 100 ms Memory Size: 128 MB Max Memory Used: 9 MB
请帮我调试错误。
【问题讨论】:
这是你的完整代码吗?由于错误,似乎在某个地方想要import lambda_function
,但没有找到。也许你想要from future import lambda_function
?或者只是 pip install lambda_function 在 cmd 行上。
@Berci 我在 AWS 平台上运行这个 python 代码。我不能使用点子。我的代码中的任何地方都在使用 lambda_function。如果我在 AWS 控制台中复制粘贴相同的代码,它将起作用
查看this thread 上的最后一条评论——也许适用于你?
我的猜测是您的函数中的“处理程序”选项不正确。检查您的文件名为“lambda_function.py”,处理程序方法是否为“lambda_handler”
我花了几个小时,终于知道你必须压缩目录的内容(包括 lambda_function.py )而不是目录。
【参考方案1】:
错误是由于 lambda 函数的文件名。在创建 lambda 函数时,它会要求 Lambda 函数处理程序。您必须将其命名为 Python_File_Name.Method_Name
。在这种情况下,我将其命名为lambda.lambda_handler
(lambda.py
是文件名)。
请在快照下方找到。
【讨论】:
我的代码只是在 lambda 中作为代码——而不是作为文件。 @BenWheeler:尽管它是内联代码,但它是您实际编写的文件。您可以在窗口左侧看到文件名和整个目录结构。 所以我将我的代码命名为“lambda_function.py”,我应该将处理程序命名为 Python_lambda_function.lambda_handler 吗? @RahulBanerjee 不,你可以称它为 lambda_function.lambda_handler 我收到了同样的错误,但是我的句柄被称为 lambda_function.lamda_handler 而我的代码被称为 lambda_function.py,它应该可以工作【参考方案2】:如果您要上传 zip 文件。确保压缩目录的内容而不是目录本身。
【讨论】:
压缩时,请确保您也使用了 -r 标志! 谢谢这解决了我的问题!【参考方案3】:此问题的另一个来源是压缩文件的权限。它必须至少在全球范围内可读。 (最小chmod 444
)
我在压缩之前在 python 文件上运行了以下内容,它运行良好。
chmod u=rwx,go=r
【讨论】:
这个。我正在使用 Python 的 ZipFile 以编程方式将 lambda 函数打包到 ZIP 中,它默认为0600
,正如你提到的那样是不够的。此外,集成的 Lambda 源代码编辑器(在 Amazon 网页上)将愉快地读取文件,而不会警告权限问题。
第二。我通过使用此处显示的方法设置文件权限使其工作:***.com/a/434689/931277【参考方案4】:
我发现 Nithin 的回答很有帮助。这是一个具体的演练:
查找这些值:
-
python 脚本中 lambda_handler 函数的名称。这
AWS 示例中使用的名称是
lambda_handler
喜欢def lambda_handler(event, context)
。在这种情况下,值为
lambda_handler
在 Lambda 仪表板中,在 lambda 仪表板的 Configuration 部分的 Handler 文本框中找到 Handler 的名称
该函数(如 Nithin 的屏幕截图所示)。我的默认名字是
lambda_function.lambda_handler
。
python 脚本的名称。假设它是cool.py
使用这些值,您需要将处理程序(如屏幕截图所示)重命名为 cool.lambda_handler
。这是摆脱 “无法导入模块 lambda_function
” 错误消息的一种方法。如果您要将 python 脚本中的处理程序重命名为 sup
,那么您需要将 lambda 仪表板中的处理程序重命名为 cool.sup
【讨论】:
【参考方案5】:这是一个快速的步骤。
假设您有一个名为 deploy
的文件夹,其中您的 lambda 文件调用 lambda_function.py
。让我们假设这个文件看起来像这样。 (p1
和p2
代表第三方包。)
import p1
import p2
def lambda_handler(event, context):
# more code here
return
"status": 200,
"body" : "Hello from Lambda!",
对于每个第三方依赖项,您需要在 deploy
文件夹中使用 pip install <third-party-package> --target .
。
pip install p1 --target .
pip install p2 --target .
完成此操作后,您的结构应该如下所示。
deploy/
├── lambda_function.py
├── p1/
│ ├── __init__.py
│ ├── a.py
│ ├── b.py
│ └── c.py
└── p2/
├── __init__.py
├── x.py
├── y.py
└── z.py
最后,你需要将zip
deploy
文件夹内的所有内容压缩成一个压缩文件。在 Mac 或 Linux 上,该命令在 deploy
文件夹中看起来像 zip -r ../deploy.zip *
。请注意,-r
标志用于递归子文件夹。
文件 zip 文件的结构应与原始文件夹相同。
deploy.zip/
├── lambda_function.py
├── p1/
│ ├── __init__.py
│ ├── a.py
│ ├── b.py
│ └── c.py
└── p2/
├── __init__.py
├── x.py
├── y.py
└── z.py
上传 zip 文件并指定 <file_name>.<function_name>
供 Lambda 进入您的流程,例如上面示例的 lambda_function.lambda_handler
。
【讨论】:
另外,不要像zip -r deploy.zip deploy
那样压缩整个文件夹。这将在 zip 文件中创建一个部署文件夹。【参考方案6】:
在为 AWS Lambda(用于 Python)创建部署包时,陷阱实在太多了。我花了好几个小时调试会话,直到找到一个很少失败的公式。
我创建了一个脚本,可以自动执行整个过程,从而减少出错的可能性。我还编写了解释一切如何工作的教程。您可能想检查一下:
Hassle-Free Python Lambda Deployment [Tutorial + Script]
【讨论】:
很棒的帖子,但我错过了最难部分的细节,即如何打包原生库。这有多复杂,真的不正常【参考方案7】:在尝试了上述所有解决方案后,我发现这很难。如果您在 zip 文件中使用子目录,请确保在每个子目录中包含 __init__.py
文件,这对我有用。
【讨论】:
【参考方案8】:在lambda_handler
中,格式必须为lambda_filename.lambda_functionName
。
假设您要运行lambda_handler
函数并且它在lambda_fuction.py
中,那么您的处理程序格式为lambda_function.lambda_handler
。
出现此错误的另一个原因是模块依赖关系。
您的lambda_fuction.py
必须位于 zip 文件的根目录中。
【讨论】:
【参考方案9】:我也有错误。
原来我的 zip 文件包含代码父文件夹。当我unzip
并检查 zip 文件时,lambda_function
文件位于父文件夹 ./lambda
下。
使用zip
命令,修复错误:
zip -r ../lambda.zip ./*
【讨论】:
在您的代码文件夹中运行 zip。我的情况是 cd lambda && zip -r ../lambda.zip ./*【参考方案10】:这里的问题是,用于构建您的 Lambda 函数依赖项(在您自己的机器上)的 Python 版本与为您的 Lambda 函数选择的 Python 版本不同。这种情况很常见,尤其是当您的依赖项中有 Numpy 库部分时。
示例:您机器的 python 版本:3.6 ---> Lambda python 版本 3.6
【讨论】:
【参考方案11】:确保您将文件夹结构中的所有依赖项压缩为 python/[Your All Dependencies] 以使其按照本文档工作。
https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html#configuration-layers-path
【讨论】:
【参考方案12】:@nithin,
AWS 在Lambda
函数中发布了layers
概念。你可以创建你的层,在那里你可以上传尽可能多的库,然后你可以将层与 lambda 函数连接起来。
更多详情:https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html
【讨论】:
【参考方案13】:2019 年的展望:
AWS Lambda 现在支持 Python 3.7,许多人(包括我自己)选择将其用作内联 lambda 的运行时。
然后我必须导入一个外部依赖项,并按照 OP 所指的那样遵循 AWS Docs。 (本地安装 --> 压缩 --> 上传)。
我遇到了导入模块错误,我意识到我的本地 PC 将 Python 2.7 作为默认 Python。当我调用 pip 时,它安装了我对 Python 2.7 的依赖项。
所以我在本地切换到与 lambda 控制台中所选运行时版本匹配的 Python 版本,然后重新安装外部依赖项。这为我解决了这个问题。例如:
$ python3 -m pip install --target path/to/lambda_file <external_dependency_name>
【讨论】:
【参考方案14】:我通过容器而不是 zip 文件构建 lambda。
解决这个问题的方法是将项目复制到“$LAMBDA_TASK_ROOT”文件夹中,而不仅仅是我选择的自定义文件夹。
FROM public.ecr.aws/lambda/python:3.8
WORKDIR $LAMBDA_TASK_ROOT
COPY requirements.txt requirements.txt
RUN pip3 install -r requirements.txt
COPY . .
CMD ["lambda_function.lambda_handler"]
尽管我之前设置了 WORKDIR,甚至尝试在 Lambda 中使用“WORKDIR override”设置,但它仅在我使用“$LAMBDA_TASK_ROOT”文件夹时才有效。
【讨论】:
【参考方案15】:我遇到了同样的问题,如果我没记错的话,这是 lynda.com 上教程的一部分。 我犯的错误是没有将运行时选择为 Python 3.6,这是 lamda 函数控制台中的一个选项。
【讨论】:
【参考方案16】:分享我对同一问题的解决方案,以防万一它对任何人都有帮助。
问题: 在执行 AWS 文章 [2] 中提供的 aws-big-data-blog 代码 [1] 时出现错误:“[ERROR] Runtime.ImportModuleError: Unable to import module 'lambda_function': No module named 'StringIO'”。
解决方案: 将运行时从 Python 3.7 更改为 Python 2.7
[1] — https://github.com/bsnively/aws-big-data-blog/blob/master/aws-blog-vpcflowlogs-athena-quicksight/CloudwatchLogsToFirehose/lambdacode.py [2] — https://aws.amazon.com/blogs/big-data/analyzing-vpc-flow-logs-with-amazon-kinesis-firehose-amazon-athena-and-amazon-quicksight/
【讨论】:
对我来说正好相反 (2.7 -> 3.8)【参考方案17】:您可以配置您的 Lambda 函数,以层的形式引入额外的代码和内容。层是包含库、自定义运行时或其他依赖项的 ZIP 存档。使用层,您可以在函数中使用库,而无需将它们包含在部署包中。层可以让您的部署包保持较小,从而使开发更容易。
参考文献:-
-
https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html
https://towardsdatascience.com/introduction-to-amazon-lambda-layers-and-boto3-using-python3-39bd390add17
【讨论】:
【参考方案18】:确保您的 lambda 函数名称和处理程序名称匹配。例如:
如果您的 lambda 函数名称是“index.py
”并且您将处理程序名称指定为“lambda_function.lambda_handler
”,那么您将收到错误消息“无法导入模块“lambda_function”:没有名为“lambda_function”的模块'。
分辨率:
您必须将 lambda_handler 名称从“lambda_function.lambda_handler
”更新为“index.lambda_handler
”
【讨论】:
【参考方案19】:转到 Lambda 函数,然后选择层,然后滚动到运行时设置并单击编辑。
您还可以使用 YAML 文件中的特定处理程序配置 SAM。下面的例子。
AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Description: An AWS Serverless Specification template describing your function.
Resources:
getRecommendation:
Type: 'AWS::Serverless::Function'
Properties:
Handler: pythonfilename.lambda_handler
Runtime: python3.7
CodeUri: .
Description: ''
MemorySize: 128
Timeout: 3
Role: 'arn:aws:iam::xxxxx:role/lambdaroleIam'
【讨论】:
【参考方案20】:你需要压缩所有的需求,使用这个脚本
#!/usr/bin/env bash
rm package.zip
mkdir package
pip install -r requirements.txt --target package
cat $1 > package/lambda_function.py
cd package
zip -r9 "../package.zip" .
cd ..
rm -rf package
用于:
package.sh <python_file>
【讨论】:
【参考方案21】:我的问题是 .py 文件和依赖项不在 zip 的“根”目录中。例如库和 lambda 函数 .py 的路径必须是:
<lambda_function_name>.py
<name of library>/foo/bar/
不是
/foo/bar/<name of library>/foo2/bar2
例如:
drwxr-xr-x 3.0 unx 0 bx stor 20-Apr-17 19:43 boto3/ec2/__pycache__/
-rw-r--r-- 3.0 unx 192 bx defX 20-Apr-17 19:43 boto3/ec2/__pycache__/__init__.cpython-37.pyc
-rw-r--r-- 3.0 unx 758 bx defX 20-Apr-17 19:43 boto3/ec2/__pycache__/deletetags.cpython-37.pyc
-rw-r--r-- 3.0 unx 965 bx defX 20-Apr-17 19:43 boto3/ec2/__pycache__/createtags.cpython-37.pyc
-rw-r--r-- 3.0 unx 7781 tx defN 20-Apr-17 20:33 download-cs-sensors-to-s3.py
【讨论】:
【参考方案22】:请在Import requests
后面加一个
import boto3
我可以看到您的代码中缺少的内容。
【讨论】:
【参考方案23】:您的 zip 中的包目录也必须是世界可读的。
要确定这是否是您的问题(Linux),请使用:
find $ZIP_SOURCE -type d -not -perm /001 -printf %M\ "%p\n"
修复使用:
find $ZIP_SOURCE -type d -not -perm /001 -exec chmod o+x \;
文件可读也是一项要求。要确定这是否是您的问题,请使用:
find $ZIP_SOURCE -type f -not -perm /004 -printf %M\ "%p\n"
修复使用:
find $ZIP_SOURCE -type f -not -perm /004 -exec chmod o+r \;
如果您遇到此问题并且您在 Linux 中工作,请检查在创建或签出 git 您的 python 包时是否正确设置了 umask,例如把它放在你的打包脚本或 .bashrc 中:
umask 0002
【讨论】:
【参考方案24】:将 python 文件名更改为 lambda_function.py,例如在我的例子中文件名是 app.py 一旦我将文件名更改为 lambda_function.py,错误就消失了
【讨论】:
【参考方案25】:TL;DR,试试chmod 755 python
我知道这已经是一个很长的话题了,但是如果您在阅读了所有社区成员在此处发布的所有潜在解决方案后仍然无法解决以下问题,您可以尝试解决我的问题的解决方案。
"errorMessage": "Unable to import module 'xxx': No module named 'yyy'",
"errorType": "Runtime.ImportModuleError",
"stackTrace": []
为了清楚起见,我说的是 Python 运行时的 AWS Lambda 层(不是部署包)的 zip 文件。在我的例子中,所有依赖项都根据doc 放在一个名为python
的文件夹下。
请注意,使用名为 python
的文件夹比使用其他文件夹结构更好,因为它不依赖于 Python 的版本。
那么您应该尝试使用以下代码 sn-p 在 Lambda 中执行ls
:
import os
def lambda_handler(event, context):
print(os.listdir('/opt'))
print(os.listdir('/opt/python'))
这是预期的输出:
['python']
['OpenSSL', '__pycache__', ... 'urllib3', 'urllib3-1.24.2.dist-info']
就我而言,在问题解决之前,输出是
"errorMessage": "[Errno 13] Permission denied: '/opt/python'",
"errorType": "PermissionError",
"stackTrace": [
" File \"/var/task/lambda_function.py\", line 16, in lambda_handler\n print(os.listdir('/opt/python'))\n"
]
因此,这显然是一个权限问题。在做了chmod 755 python
、zip -r9 lambda-layer python
,并将lambda-layer.zip
上传到Lambda之后,问题就解决了。
【讨论】:
【参考方案26】:为遇到相同问题的其他人添加此答案,并且没有其他解决方案适用于他们。如果您已将代码上传到 lambda,并尝试在不单击 Deploy 的情况下对其进行测试,则会观察到相同的错误;您必须在能够运行测试之前部署 lambda。
【讨论】:
【参考方案27】:我正在参加一个涉及 Lambda 函数的 AWS 培训课程。这似乎很基本,但您必须选择 Deploy 才能使测试事件生效 - 特别是如果您上传的代码不包含 lambda_function.lambda_handler
方法 - 这是我的错误。在我的培训中,我并不清楚这一点,因此在这个愚蠢的错误上浪费了 30 多分钟。
【讨论】:
【参考方案28】:不确定上面是否提到过,但 .zip 文件名和 zip 的内容应该匹配。 例如:文件:lambda.zip 和内容:lambda.py
【讨论】:
以上是关于python中的AWS Lambda导入模块错误的主要内容,如果未能解决你的问题,请参考以下文章
AWS Lambda python 错误:Runtime.ImportModuleError:无法导入模块“app”:无法从“pyparsing”导入名称“operatorPrecedence”
如何从 aws lambda 中的 git 子模块导入代码?
aws lambda 无法导入模块“lambda_function”:没有名为“requests”的模块
AWS Lambda NodeJS导入返回空模块,但仅在AWS中