Błąd modułu importu AWS Lambda w Pythonie

93

Tworzę pakiet wdrożeniowy AWS Lambda Python. Używam jednego zewnętrznego żądania zależności. Zainstalowałem zewnętrzną zależność, korzystając z dokumentacji AWS http://docs.aws.amazon.com/lambda/latest/dg/lambda-python-how-to-create-deployment-package.html . Poniżej znajduje się mój kod w Pythonie.

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

Utworzono Zip zawartość katalogu project-dir i przesłano do lambda (Zip zawartość katalogu, a nie katalog). Kiedy wykonuję funkcję, pojawia się poniższy błąd.

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

Prosimy o pomoc w usunięciu błędu.

Nithin K Anil
źródło
Czy to Twój pełny kod? Przez błąd wydaje się, że gdzieś chciałoby się coś, import lambda_functionczego nie znaleziono. Może chcesz from future import lambda_function? Lub po prostu pip zainstaluj lambda_function w linii cmd.
Berci,
@Berci Jestem uruchamiany na platformie AWS w języku Python. Nie mogę użyć pip. gdziekolwiek w moim kodzie używam lambda_function. JEŚLI
skopiuję, wklejam
Zobacz ostatni komentarz w tym wątku - może dotyczy Ciebie?
kwinkunks
@kwinkunks Próbowałem tego. Właściwie spakuję zawartość, a nie katalog !!
Nithin K Anil
2
Domyślam się, że opcja „handler” w twojej funkcji jest nieprawidłowa. Sprawdź, czy nazwa pliku o nazwie „lambda_function.py” i metoda obsługi to „lambda_handler”
Vor,

Odpowiedzi:

110

Błąd spowodowany nazwą pliku funkcji lambda. Podczas tworzenia funkcji lambda zapyta o handler funkcji lambda. Musisz nadać mu nazwę Python_File_Name.Method_Name . W tym scenariuszu nazwałem go jako lambda.lambda_handler (lambda.py to nazwa pliku).

Poniżej migawka. wprowadź opis obrazu tutaj

Nithin K Anil
źródło
1
Mój kod jest po prostu w lambdzie jako kod - nie jako plik.
Ben Wheeler
4
@BenWheeler: Mimo że jest to kod wbudowany, zapisujesz go w pliku. Możesz zobaczyć nazwę pliku i całą strukturę katalogów po lewej stronie okna.
Vineeth
Więc nazwałem swój kod jako „lambda_function.py”, czy powinienem nazwać program obsługi jako Python_lambda_function.lambda_handler?
RB17
@RahulBanerjee Nie. Nazwałbyś to lambda_function.lambda_handler
Dinesh
90

Jeśli przesyłasz plik zip. Upewnij się, że kompresujesz zawartość katalogu, a nie sam katalog.

2ank3th
źródło
2
Podczas pakowania upewnij się, że używasz również flagi -r!
Grant Robert Smith
@ 2ank3. Jesteś najlepszy
Sethuraman Srinivasan
Dzięki za to.
JamesG
24

Innym źródłem tego problemu są uprawnienia do spakowanego pliku. To musi być co najmniej na całym świecie czytelny. (min chmod 444)

Uruchomiłem następujące polecenie na pliku Pythona przed spakowaniem go i działało dobrze.

chmod u=rwx,go=r
Catalin Ciurea
źródło
4
To. Używałem Pythona ZipFile do programowego spakowania funkcji lambda do ZIP, domyślnie posiadanie 0600tego, jak wspomniałeś, nie wystarczy. Ponadto zintegrowany edytor kodu źródłowego Lambda (na stronie internetowej Amazon) z przyjemnością odczyta plik bez ostrzeżenia o problemach z uprawnieniami.
cjhanks
2
Druga. Mam to działające, ustawiając uprawnienia do plików za pomocą metody pokazanej tutaj: stackoverflow.com/a/434689/931277
dokkaebi
15

Odpowiedź Nithina okazała się bardzo pomocna. Oto konkretny przewodnik:

Wyszukaj te wartości:

  1. Nazwa funkcji lambda_handler w skrypcie w Pythonie. Nazwa użyta w przykładach AWS to „lambda_handler” przypominająca „def lambda_handler (zdarzenie, kontekst)”. W tym przypadku wartością jest „lambda_handler”
  2. Na pulpicie Lambda znajdź nazwę Handler w polu tekstowym "Handler" w sekcji "Konfiguracja" na pulpicie lambda dla funkcji (pokazane na zrzucie ekranu Nithina). Moja domyślna nazwa to „lambda_function.lambda_handler”.
  3. Nazwa twojego skryptu w Pythonie. Powiedzmy, że to „cool.py”

Mając te wartości, należałoby zmienić nazwę programu obsługi (pokazaną na zrzucie ekranu) na „cool.lambda_handler”. Jest to jeden ze sposobów na pozbycie się komunikatu o błędzie „Nie można zaimportować modułu 'lambda_function'”. Jeśli miałbyś zmienić nazwę handlera w swoim skrypcie Pythona na "sup", to musiałbyś zmienić nazwę handlera w dashboardzie lambda na "cool.sup"

user3303554
źródło
11

Podczas tworzenia pakietów wdrożeniowych dla AWS Lambda (dla Pythona) jest tak wiele problemów . Spędziłem wiele godzin na sesjach debugowania, dopóki nie znalazłem formuły, która rzadko zawodzi.

Stworzyłem skrypt, który automatyzuje cały proces i dzięki temu jest mniej podatny na błędy. Napisałem również poradnik wyjaśniający, jak wszystko działa. Możesz to sprawdzić:

Bezproblemowe wdrażanie Lambda w języku Python [samouczek + skrypt]

joarleymoraes
źródło
2
Świetny post, ale brakuje mi szczegółów najtrudniejszej części, czyli sposobu pakowania natywnych bibliotek. To naprawdę nie jest normalne, jak skomplikowane to jest
JohnAndrews
10

Oto szybki krok.

Załóżmy, że masz folder o nazwie deploy, z plikiem lambda wewnątrz wywołania lambda_function.py. Załóżmy, że ten plik wygląda mniej więcej tak. ( p1i p2reprezentują pakiety stron trzecich).

import p1
import p2

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

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

W przypadku każdej zależności innej firmy musisz przejść pip install <third-party-package> --target .z poziomu deployfolderu.

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

Gdy to zrobisz, oto jak powinna wyglądać twoja struktura.

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

Na koniec musisz zipcałą zawartość deployfolderu do skompresowanego pliku. Na komputerze Mac lub Linux polecenie wyglądałoby jak zip -r ../deploy.zip *z deployfolderu. Zauważ, że -rflaga dotyczy rekurencyjnych podfolderów.

Struktura pliku zip powinna odzwierciedlać oryginalny folder.

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

Prześlij plik zip i określ <file_name>.<function_name>dla Lambda, aby wejść do twojego procesu, tak jak lambda_function.lambda_handlerw powyższym przykładzie.

openwonk
źródło
1
Ponadto NIE ZAPAKUJ całego folderu, np zip -r deploy.zip deploy. Spowoduje to utworzenie folderu wdrażania w pliku zip.
openwonk
9

Po wypróbowaniu wszystkich powyższych rozwiązań okazało się to trudne. Jeśli używasz podkatalogów w pliku zip, upewnij się, że umieściłeś __init__.pyplik w każdym z podkatalogów i to zadziałało.

KApuri
źródło
7

Ja też miałem błąd. Okazuje się, że mój plik zip zawiera folder nadrzędny kodu. Kiedy unzipsprawdzam plik zip, lambda_functionplik znajduje się w folderze nadrzędnym ./lambda.

Użyj zippolecenia, napraw błąd:

zip -r ../lambda.zip ./*
Joe
źródło
1
uruchom zip wewnątrz folderu kodu. moja sprawa tutaj, cd lambda && zip -r ../lambda.zip ./*
Joe
4

W lambda_handler formacie musi być lambda_filename.lambda_functionName. Przypuśćmy, że chcesz uruchomić lambda_handlerfunkcję i jest w lambda_fuction.py, to format twojego modułu obsługi to lambda_function.lambda_handler.

Innym powodem wystąpienia tego błędu są zależności modułów.

Twój lambda_fuction.pymusi znajdować się w katalogu głównym pliku zip.

PKP
źródło
2

Perspektywa z 2019 roku:

AWS Lambda obsługuje teraz Python 3.7, którego wiele osób (w tym ja) wybiera jako środowisko uruchomieniowe dla wbudowanych lambd.

Następnie musiałem zaimportować zewnętrzną zależność i postępowałem zgodnie z dokumentami AWS jako OP. (instalacja lokalna -> zip -> przesyłanie).

Wystąpił błąd modułu importu i zdałem sobie sprawę, że mój lokalny komputer ma Python 2.7 jako domyślny Python. Kiedy wywołałem pip, zainstalowałem moją zależność dla Pythona 2.7.

Więc przełączyłem się lokalnie na wersję Pythona, która pasuje do wybranej wersji środowiska uruchomieniowego w konsoli lambda, a następnie ponownie zainstalowałem zewnętrzne zależności. To rozwiązało problem. Na przykład:

$ python3 -m pip install --target path/to/lambda_file <external_dependency_name>
l001d
źródło
1

Wpadłem na ten sam problem, to było ćwiczenie jako część samouczka na lynda.com, jeśli się nie mylę. Błąd, który popełniłem, polegał na tym, że nie wybrałem środowiska wykonawczego jako Python 3.6, co jest opcją w konsoli funkcji lamda.

Nadeem
źródło
1

Problem polega na tym, że wersja Pythona użyta do zbudowania zależności funkcji Lambda (na własnej maszynie) jest inna niż wybrana wersja Pythona dla funkcji Lambda. Ten przypadek jest powszechny, zwłaszcza jeśli biblioteka Numpy jest częścią twoich zależności.

Przykład: Wersja pythona twojego komputera: 3.6 ---> Lambda python w wersji 3.6

Sharhabeel Hamdan
źródło
0

Musisz spakować wszystkie wymagania, użyj tego skryptu

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

używać z:

package.sh <python_file>
Uri Goren
źródło
0

Udostępniam moje rozwiązanie tego samego problemu, na wszelki wypadek, gdyby to komukolwiek pomogło.

Problem: Wystąpił błąd: „[ERROR] Runtime.ImportModuleError: Nie można zaimportować modułu„ lambda_function ”: brak modułu o nazwie„ StringIO ”” podczas wykonywania kodu aws-big-data-blog [1] podanego w artykule AWS [2].

Rozwiązanie: Zmieniono środowisko wykonawcze z Python 3.7 na 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 / analysing-vpc-flow-logs-with-amazon-kinesis-firehose-amazon-athena-and-amazon-quicksight /

user72789
źródło
Dla mnie było odwrotnie (2,7 -> 3,8)
demonicdaron
0

Możesz skonfigurować swoją funkcję Lambda, aby pobierała dodatkowy kod i zawartość w postaci warstw. Warstwa to archiwum ZIP zawierające biblioteki, niestandardowe środowisko wykonawcze lub inne zależności. Dzięki warstwom możesz używać bibliotek w swojej funkcji bez konieczności dołączania ich do pakietu wdrożeniowego. Warstwy pozwalają zachować mały pakiet wdrożeniowy, co ułatwia programowanie.

Bibliografia:-

  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
źródło
0

Mój problem polegał na tym, że plik .py i zależności nie znajdowały się w katalogu głównym zip. np. ścieżka do bibliotek i funkcji lambda .py musi być:

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

nie

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

Na przykład:

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
źródło
0

Właściwie przejdź do głównego folderu (pakietu wdrożeniowego), który chcesz spakować,

Wewnątrz tego folderu wybierz wszystkie pliki, a następnie utwórz plik zip i prześlij ten plik zip

MUHAMMAD ZEESHAN
źródło
0

Dodaj poniżej jeden po Import requests

import boto3

To, co widzę, brakuje w Twoim kodzie.

Mrinal
źródło