python 中的 AWS Lambda 导入模块错误

AWS Lambda import module error in python

我正在创建一个 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(Zip 目录内容,而不是目录)。当我执行该功能时,出现以下错误。

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

请帮我调试错误。

错误是由于 lambda 函数的文件名引起的。在创建 lambda 函数时,它将请求 Lambda 函数处理程序。您必须将其命名为 Python_File_Name.Method_Name。在这种情况下,我将其命名为lambda.lambda_handlerlambda.py是文件名)。

请在下面找到快照。

我发现 Nithin 的回答很有帮助。这是一个具体的演练:

查找这些值:

  1. python 脚本中 lambda_handler 函数的名称。这 AWS 示例中使用的名称是 lambda_handler looking 喜欢 def lambda_handler(event, context)。在这种情况下,值为 lambda_handler
  2. 在 Lambda 仪表板中,在 Lambda 仪表板的 Configuration 部分的 Handler 文本框中找到 Handler 的名称为了 函数(如 Nithin 的屏幕截图所示)。我的默认名字是 lambda_function.lambda_handler.
  3. 您的 python 脚本的名称。假设它是 cool.py

使用这些值,您需要将处理程序(如屏幕截图所示)重命名为 cool.lambda_handler。这是摆脱 “无法导入模块 lambda_function 错误消息的一种方法。如果您要将 python 脚本中的处理程序重命名为 sup,那么您需要将 lambda 仪表板中的处理程序重命名为 cool.sup

此问题的另一个来源是压缩文件的权限。它必须 至少是全球可读的。 (分钟chmod 444)

我 运行 在 python 文件上压缩它之前,它工作正常。

chmod u=rwx,go=r

在为 AWS Lambda(针对 Python)创建部署包时,有很多 陷阱 。我花了很多时间调试会话,直到找到一个很少失败的公式。

我已经创建了一个脚本来自动执行整个过程,因此不容易出错。我还写了教程来解释一切是如何工作的。您可能想检查一下:

Hassle-Free Python Lambda Deployment [Tutorial + Script]

如果您上传的是 zip 文件。确保您正在压缩目录的内容而不是目录本身。

在尝试了上述所有解决方案后,我发现这条路很难走。如果您在 zip 文件中使用子目录,请确保在每个子目录中包含 __init__.py 文件并且对我有用。

我也有这个错误。 原来我的 zip 文件包含代码父文件夹。当我 unzip 并检查 zip 文件时,lambda_function 文件位于父文件夹 ./lambda.

使用zip命令,修复错误:

zip -r ../lambda.zip ./*

我 运行 遇到了同样的问题,如果我没记错的话,这是 lynda.com 教程的一部分练习。 我犯的错误是没有将运行时选择为 Python 3.6,这是 lamda 函数控制台中的一个选项。

您需要压缩所有要求,使用此脚本

#!/usr/bin/env bash
rm package.zip
mkdir package
pip install -r requirements.txt --target package
cat  > package/lambda_function.py
cd package
zip -r9 "../package.zip" .
cd ..
rm -rf package

用于:

package.sh <python_file>

@nithin, AWS 在 Lambda 个函数中发布了 layers 个概念。您可以创建自己的层,在那里您可以上传尽可能多的库,然后您可以将层与 lambda 函数连接起来。 更多详情:https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html

lambda_handler 中,格式必须是 lambda_filename.lambda_functionName。 假设你想要 运行 lambda_handler 函数并且它在 lambda_fuction.py 中,那么你的处理程序格式是 lambda_function.lambda_handler.

出现此错误的另一个原因是模块依赖性。

您的 lambda_fuction.py 必须在 zip 文件的根目录中。

2019 年的观点:

A​​WS Lambda 现在支持 Python 3.7,许多人(包括我自己)选择将其用作内联 lambda 的运行时。

然后我不得不导入一个外部依赖项,并且我按照 OP 所指的方式遵循了 AWS Docs。 (本地安装 --> zip --> 上传)。

我遇到了导入模块错误,我意识到我的本地 PC 默认 Python 2.7 Python。当我调用 pip 时,它安装了我对 Python 2.7.

的依赖项

所以我在本地切换到与lambda控制台中所选运行时版本匹配的Python版本,然后重新安装外部依赖项。这为我解决了问题。例如:

$ python3 -m pip install --target path/to/lambda_file <external_dependency_name>

这是一个快速步骤。

假设您有一个名为 deploy 的文件夹,其中包含调用 lambda_function.py 中的 lambda 文件。让我们假设这个文件看起来像这样。 (p1p2 代表第三方包。)

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

最后,您需要zipdeploy文件夹内的所有内容压缩成一个压缩文件。在 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

分享我对同一问题的解决方案,以防对任何人有帮助。

问题: 我收到错误消息:“[ERROR] Runtime.ImportModuleError:无法导入模块 'lambda_function':没有名为 'StringIO' 的模块”,同时执行 AWS 文章中提供的 aws-big-data-blog 代码 [1] [2].

解决方法: 将运行时从 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/

您可以将 Lambda 函数配置为以层的形式提取额外的代码和内容。层是包含库、自定义运行时或其他依赖项的 ZIP 存档。通过层,您可以在函数中使用库,而无需将它们包含在部署包中。层可让您保持部署包较小,从而使开发更容易。

参考资料:-

  1. https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html
  2. https://towardsdatascience.com/introduction-to-amazon-lambda-layers-and-boto3-using-python3-39bd390add17

确保将所有依赖项压缩为文件夹结构中的 python/[您的所有依赖项] 以使其按照本文档工作。

https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html#configuration-layers-path

我的问题是 .py 文件和依赖项不在 zip 的 "root" 目录中。例如,库和 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

请在Import requests

后加以下一项

import boto3

我看到您的代码中缺少的内容。

这里的问题是,用于构建 Lambda 函数依赖项(在您自己的计算机上)的 Python 版本与为您的 Lambda 函数选择的 Python 版本不同。这种情况很常见,尤其是当您的依赖项中包含 Numpy 库时。

示例:您机器的 python 版本:3.6 ---> Lambda python 版本 3.6

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 

将 python 文件名更改为 lambda_function.py,例如我的文件名是 app.py 一旦我将文件名更改为 lambda_function.py

,错误就消失了

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 的版本。

那么您应该尝试使用以下代码片段在 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 pythonzip -r9 lambda-layer python 并上传 lambda-layer.zip 到 Lambda 后,问题就解决了。

我是通过容器而不是 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}”文件夹时有效。

为遇到同样问题的其他人添加此答案,none 其他解决方案对他们有效。如果您已将代码上传到 lambda 并尝试在不单击 Deploy 的情况下对其进行测试,则会出现相同的错误;您必须 部署 lambda 才能运行 测试。

确保您的 lambda 函数名称和处理程序名称匹配。例如: 如果您的 lambda 函数名称是“index.py”并且您将处理程序名称指定为“lambda_function.lambda_handler”,那么您将收到错误消息“无法导入模块 'lambda_function':没有名为 'lambda_function'.

的模块

决议: 您必须将 lambda_handler 名称从“lambda_function.lambda_handler”更新为“index.lambda_handler

我正在参加一个通过 Lambda 函数的 AWS 培训课程。这看起来很基本,但您必须选择 Deploy 才能使测试事件起作用 - 特别是如果您上传的代码不包含 lambda_function.lambda_handler 方法 - 这是我的错误。通过我的培训,我并不清楚这一点,因此在这个愚蠢的错误上损失了 30 多分钟。

不确定上面是否提到过,但是 .zip 文件名和 zip 的内容应该匹配。 例如:文件:lambda.zip 和内容:lambda.py

转到 Lambda 函数,然后 select 层,然后滚动到运行时设置并单击编辑。

您还可以在 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'

这是因为您的代码可能包含一些 lambda 函数未知的包(例如 python 的请求模块)。为了解决这个问题,AWS 在 Lambda 函数中引入了层的概念,在那里你可以上传尽可能多的库,然后你可以将层与 Lambda 函数连接起来。