Erro do módulo de importação do AWS Lambda em python

98

Estou criando um pacote de implantação python AWS Lambda. Estou usando uma solicitação de dependência externa. Instalei a dependência externa usando a documentação AWS http://docs.aws.amazon.com/lambda/latest/dg/lambda-python-how-to-create-deployment-package.html . Abaixo está o meu código 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

Criou o Zip do conteúdo do diretório project-dir e carregou no lambda (Zip o conteúdo do diretório, não o diretório). Quando estou executando a função, recebo o erro mencionado abaixo.

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

Por favor, ajude-me a depurar o erro.

Nithin K Anil
fonte
É o seu código completo? Pelo erro parece que em algum lugar algo gostaria import lambda_functionque não foi encontrado. Talvez você queira from future import lambda_function? Ou apenas instale lambda_function na linha cmd.
Berci de
@Berci estou executando este código python na plataforma AWS. Eu não posso usar pip. em qualquer lugar no meu código estou usando lambda_function. SE eu copiar e colar o mesmo código no console da AWS, ele funcionará
Nithin K Anil
Veja o último comentário neste tópico - talvez se aplique a você?
kwinkunks de
@kwinkunks eu tentei isso. Na verdade estou compactando o conteúdo, não o diretório !!
Nithin K Anil
2
Meu palpite é que a opção "manipulador" em sua função está incorreta. Verifique se o nome do arquivo chamado "lambda_function.py" e o método do manipulador é "lambda_handler"
Vor

Respostas:

115

O erro ocorreu devido ao nome do arquivo da função lambda. Ao criar a função lambda, ele solicitará o manipulador de função Lambda. Você deve nomeá-lo como seu Python_File_Name.Method_Name . Neste cenário, chamei-o de lambda.lambda_handler (lambda.py é o nome do arquivo).

Encontre abaixo o instantâneo. insira a descrição da imagem aqui

Nithin K Anil
fonte
1
Meu código está apenas em lambda como código - não como um arquivo.
Ben Wheeler
4
@BenWheeler: Embora seja um código embutido, é para um arquivo que você realmente o escreve. Você pode ver o nome do arquivo e toda a estrutura do diretório à esquerda da janela.
Vineeth
Portanto, nomeei meu código como "lambda_function.py", devo nomear o manipulador como Python_lambda_function.lambda_handler?
RB17
@RahulBanerjee Não. Você o chamaria de lambda_function.lambda_handler
Dinesh
98

Se você estiver enviando um arquivo zip. Certifique-se de compactar o conteúdo do diretório e não o diretório em si.

2ank3
fonte
3
Ao compactar, certifique-se de usar a sinalização -r também!
Grant Robert Smith
@ 2ank3th você é o melhor
Sethuraman Srinivasan
Obrigado por isso.
JamesG
24

Outra fonte desse problema são as permissões do arquivo compactado. Ele deve ser, pelo menos a nível mundial legível. (min chmod 444)

Corri o seguinte no arquivo python antes de compactá-lo e funcionou bem.

chmod u=rwx,go=r
Catalin Ciurea
fonte
4
Este. Eu estava usando o ZipFile do Python para empacotar programaticamente as funções lambda no ZIP, o padrão é 0600que, como você mencionou, não é suficiente. Além disso, o editor de código-fonte Lambda integrado (na página da Web da Amazon) lerá o arquivo sem avisar sobre problemas de permissão.
Obrigado,
2
Segundo. Eu fiz isso funcionar definindo permissões de arquivo usando o método mostrado aqui: stackoverflow.com/a/434689/931277
dokkaebi
16

Achei a resposta de Nithin muito útil. Aqui está um guia específico:

Pesquise estes valores:

  1. O nome da função lambda_handler em seu script Python. O nome usado nos exemplos da AWS é "lambda_handler" parecido com "def lambda_handler (evento, contexto)". Nesse caso, o valor é "lambda_handler"
  2. No painel do Lambda, encontre o nome do Manipulador na caixa de texto "Manipulador" na seção "Configuração" no painel do lambda para a função (mostrado na captura de tela de Nithin). Meu nome padrão era "lambda_function.lambda_handler".
  3. O nome do seu script Python. Digamos que seja "cool.py"

Com esses valores, você precisaria renomear o manipulador (mostrado na captura de tela) para "cool.lambda_handler". Esta é uma maneira de se livrar da mensagem de erro "Não foi possível importar o módulo 'lambda_function'". Se você fosse renomear o manipulador em seu script python para "sup", seria necessário renomear o manipulador no painel lambda para "cool.sup"

user3303554
fonte
11

Existem muitas pegadinhas ao criar pacotes de implantação para AWS Lambda (para Python). Passei horas e horas em sessões de depuração até encontrar uma fórmula que raramente falha.

Criei um script que automatiza todo o processo e, portanto, o torna menos sujeito a erros. Também escrevi um tutorial que explica como tudo funciona. Você pode querer dar uma olhada:

Implantação do Python Lambda sem complicações [Tutorial + Script]

joarleymoraes
fonte
2
Ótimo post, mas sinto falta de detalhes na parte mais difícil que é como empacotar bibliotecas nativas. Realmente não é normal quão complexo isso é
JohnAndrews
10

Aqui está um rápido passo a passo.

Suponha que você tenha uma pasta chamada deploy, com seu arquivo lambda chamado lambda_function.py. Vamos supor que esse arquivo se pareça com isso. ( p1e p2representam pacotes de terceiros.)

import p1
import p2

def lambda_handler(event, context):
    # more code here

    return {
        "status": 200,
        "body" : "Hello from Lambda!",
    }

Para cada dependência de terceiros, você precisa pip install <third-party-package> --target .de dentro da deploypasta.

pip install p1 --target .
pip install p2 --target .

Depois de fazer isso, veja como sua estrutura deve se parecer.

deploy/
├── lambda_function.py
├── p1/
│   ├── __init__.py
│   ├── a.py
│   ├── b.py
│   └── c.py
└── p2/
    ├── __init__.py
    ├── x.py
    ├── y.py
    └── z.py

Finalmente, você precisa de ziptodo o conteúdo da deploypasta para um arquivo compactado. Em um Mac ou Linux, o comando teria a aparência zip -r ../deploy.zip *de dentro da deploypasta. Observe que o -rsinalizador é para subpastas recursivas.

A estrutura do arquivo zip do arquivo deve espelhar a pasta original.

deploy.zip/
├── lambda_function.py
├── p1/
│   ├── __init__.py
│   ├── a.py
│   ├── b.py
│   └── c.py
└── p2/
    ├── __init__.py
    ├── x.py
    ├── y.py
    └── z.py

Faça upload do arquivo zip e especifique o <file_name>.<function_name>para o Lambda entrar em seu processo, como lambda_function.lambda_handlerno exemplo acima.

openwonk
fonte
1
Além disso, NÃO zip a pasta inteira como zip -r deploy.zip deploy. Isso criará uma pasta de implantação dentro do arquivo zip.
openwonk em
9

Achei esse caminho difícil depois de tentar todas as soluções acima. Se você estiver usando subdiretórios no arquivo zip, certifique-se de incluir o __init__.pyarquivo em cada um dos subdiretórios e isso funcionou para mim.

KApuri
fonte
7

Eu também tive o erro. Acontece que meu arquivo zip inclui a pasta pai do código. Quando eu unzipe inspeciono o arquivo zip, o lambda_functionarquivo está na pasta pai ./lambda.

Use o zipcomando para corrigir o erro:

zip -r ../lambda.zip ./*
Joe
fonte
1
execute o zip dentro de sua pasta de código. meu caso aqui, cd lambda && zip -r ../lambda.zip ./*
Joe
4

No lambda_handlerformato deve ser lambda_filename.lambda_functionName. Supondo que você deseja executar a lambda_handlerfunção e ela está lambda_fuction.pyativada, o formato do manipulador está lambda_function.lambda_handler.

Outro motivo para obter esse erro são as dependências do módulo.

Você lambda_fuction.pydeve estar no diretório raiz do arquivo zip.

PKP
fonte
2

@nithin, a AWS lançou o layersconceito de Lambdafunções internas . Você pode criar sua camada e lá você pode carregar tanto quanto bibliotecas e então você pode conectar a camada com as funções lambda. Para mais detalhes: https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html

muTheTechie
fonte
2

Uma perspectiva de 2019:

O AWS Lambda agora oferece suporte a Python 3.7, que muitas pessoas (inclusive eu) optam por usar como o tempo de execução para lambdas em linha.

Então eu tive que importar uma dependência externa e segui o AWS Docs como o OP referido. (instalação local -> zip -> upload).

Eu tive o erro do módulo de importação e percebi que meu PC local tinha Python 2.7 como o Python padrão. Quando invoquei o pip, ele instalou minha dependência para Python 2.7.

Portanto, mudei localmente para a versão Python que corresponde à versão de tempo de execução selecionada no console lambda e reinstalei as dependências externas. Isso resolveu o problema para mim. Por exemplo:

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

Eu tive o mesmo problema, este era um exercício como parte de um tutorial no lynda.com, se não estou errado. O erro que cometi foi não selecionar o runtime como Python 3.6, que é uma opção no console de funções lamda.

Nadeem
fonte
1

O problema aqui que a versão Python usada para construir suas dependências de função Lambda (em sua própria máquina) é diferente da versão Python selecionada para sua função Lambda. Este caso é comum, especialmente se a biblioteca Numpy fizer parte de suas dependências.

Exemplo: a versão python de sua máquina: 3.6 ---> Lambda python versão 3.6

Sharhabeel Hamdan
fonte
0

Você precisa compactar todos os requisitos, use este script

#!/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

usar com:

package.sh <python_file>
Uri Goren
fonte
0

Compartilhando minha solução para o mesmo problema, apenas no caso de ajudar alguém.

Problema: recebi o erro: "[ERROR] Runtime.ImportModuleError: Não foi possível importar o módulo 'lambda_function': Nenhum módulo chamado 'StringIO'" ao executar o código do aws-big-data-blog [1] fornecido no artigo da AWS [2].

Solução: Tempo de execução alterado de Python 3.7 para 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 / analisando-vpc-flow-logs-with-amazon-kinesis-firehose-amazon-athena-and-amazon-quicksight /

user72789
fonte
Foi o contrário para mim (2,7 -> 3,8)
demonicdaron
0

Você pode configurar sua função Lambda para obter código e conteúdo adicionais na forma de camadas. Uma camada é um arquivo ZIP que contém bibliotecas, um tempo de execução personalizado ou outras dependências. Com camadas, você pode usar bibliotecas em sua função sem precisar incluí-las em seu pacote de implantação. As camadas permitem que você mantenha seu pacote de implantação pequeno, o que torna o desenvolvimento mais fácil.

Referências:-

  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
Rahul Satal
fonte
0

Meu problema era que o arquivo .py e as dependências não estavam no diretório "raiz" do zip. por exemplo, o caminho das bibliotecas e da função lambda .py deve ser:

<lambda_function_name>.py
<name of library>/foo/bar/

não

/foo/bar/<name of library>/foo2/bar2

Por exemplo:

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
lobi
fonte
0

Na verdade, vá para a pasta principal (pacote de implantação) que deseja compactar,

Dentro dessa pasta, selecione todos os arquivos e, em seguida, crie o zip e carregue esse zip

MUHAMMAD ZEESHAN
fonte
0

Adicione abaixo um depois Import requests

import boto3

O que posso ver que está faltando em seu código.

Mrinal
fonte