1. Wprowadzenie
Python to popularny język programowania typu open source wykorzystywany przez badaczy danych, programistów aplikacji internetowych i administratorów systemów.
Cloud Functions to bezserwerowa platforma obliczeniowa oparta na zdarzeniach. Cloud Functions umożliwia pisanie kodu bez obaw o udostępnianie zasobów czy skalowanie pod kątem zmieniających się wymagań.
Istnieją 2 typy funkcji w Cloud Functions:
- Funkcje HTTP odpowiadają na żądania HTTP. W ramach tego ćwiczenia z programowania utworzysz kilka takich narzędzi.
- Funkcje działające w tle są wyzwalane przez zdarzenia, takie jak opublikowanie wiadomości w Cloud Pub/Sub lub przesłanie pliku do Cloud Storage. W tym module nie omawiamy tej kwestii, ale możesz dowiedzieć się więcej w dokumentacji.
Dzięki temu ćwiczeniu w Codelabs dowiesz się, jak utworzyć własne funkcje Cloud Functions w Pythonie.
Co utworzysz
W ramach tego ćwiczenia w Codelabs opublikujesz funkcję w Cloud Functions, która po wywołaniu przez HTTP wyświetla interfejs „Python Powered” logo:
Czego się nauczysz
- Jak napisać funkcję HTTP w Cloud Functions.
- Jak napisać funkcję HTTP w Cloud Functions, która przyjmuje argumenty.
- Jak przetestować funkcję HTTP w Cloud Functions.
- Jak uruchomić lokalny serwer HTTP Pythona, aby wypróbować funkcję.
- Jak napisać funkcję HTTP w Cloud Functions, która zwraca obraz.
2. Konfiguracja i wymagania
Samodzielne konfigurowanie środowiska
- Zaloguj się w konsoli Google Cloud i utwórz nowy projekt lub wykorzystaj już istniejący. Jeśli nie masz jeszcze konta Gmail ani Google Workspace, musisz je utworzyć.
- Nazwa projektu jest wyświetlaną nazwą uczestników tego projektu. To ciąg znaków, który nie jest używany przez interfejsy API Google. W każdej chwili możesz ją zaktualizować.
- Identyfikator projektu jest unikalny we wszystkich projektach Google Cloud i nie można go zmienić (po jego ustawieniu nie można go zmienić). Cloud Console automatycznie wygeneruje unikalny ciąg znaków. zwykle nieważne, co ona jest. W większości ćwiczeń w Codelabs musisz podać swój identyfikator projektu (zwykle identyfikowany jako
PROJECT_ID
). Jeśli nie podoba Ci się wygenerowany identyfikator, możesz wygenerować kolejny losowy. Możesz też spróbować własnych sił i sprawdzić, czy jest dostępna. Po wykonaniu tej czynności nie można jej już zmienić. Pozostanie ona przez cały czas trwania projektu. - Jest jeszcze trzecia wartość, numer projektu, z którego korzystają niektóre interfejsy API. Więcej informacji o wszystkich 3 wartościach znajdziesz w dokumentacji.
- Następnie musisz włączyć płatności w Cloud Console, aby korzystać z zasobów Cloud/interfejsów API. Ukończenie tego ćwiczenia z programowania nic nie kosztuje. Aby wyłączyć zasoby w celu uniknięcia naliczania opłat po zakończeniu tego samouczka, możesz usunąć utworzone zasoby lub projekt. Nowi użytkownicy Google Cloud mogą skorzystać z programu bezpłatnego okresu próbnego o wartości 300 USD.
Uruchamianie Cloud Shell
Google Cloud można obsługiwać zdalnie z laptopa, ale w ramach tego ćwiczenia z programowania wykorzystasz Cloud Shell – środowisko wiersza poleceń działające w Cloud.
Aktywowanie Cloud Shell
- W konsoli Cloud kliknij Aktywuj Cloud Shell .
Jeśli uruchamiasz Cloud Shell po raz pierwszy, zobaczysz ekran pośredni z opisem tej usługi. Jeśli wyświetlił się ekran pośredni, kliknij Dalej.
Uzyskanie dostępu do Cloud Shell i połączenie się z nim powinno zająć tylko kilka chwil.
Ta maszyna wirtualna ma wszystkie potrzebne narzędzia dla programistów. Zawiera stały katalog domowy o pojemności 5 GB i działa w Google Cloud, co znacznie zwiększa wydajność sieci i uwierzytelnianie. Większość zadań w ramach tego ćwiczenia z programowania można wykonać w przeglądarce.
Po nawiązaniu połączenia z Cloud Shell powinno pojawić się potwierdzenie, że użytkownik jest uwierzytelniony, a projekt jest ustawiony na identyfikator Twojego projektu.
- Uruchom to polecenie w Cloud Shell, aby potwierdzić, że jesteś uwierzytelniony:
gcloud auth list
Dane wyjściowe polecenia
Credentialed Accounts ACTIVE ACCOUNT * <my_account>@<my_domain.com> To set the active account, run: $ gcloud config set account `ACCOUNT`
- Uruchom to polecenie w Cloud Shell, aby sprawdzić, czy polecenie gcloud zna Twój projekt:
gcloud config list project
Dane wyjściowe polecenia
[core] project = <PROJECT_ID>
Jeśli tak nie jest, możesz go ustawić za pomocą tego polecenia:
gcloud config set project <PROJECT_ID>
Dane wyjściowe polecenia
Updated property [core/project].
Sprawdź, czy interfejsy Cloud Functions i Cloud Build API są włączone
Uruchom to polecenie w Cloud Shell, aby sprawdzić, czy interfejsy Cloud Functions i interfejsy Cloud Build API są włączone:
gcloud services enable \ cloudfunctions.googleapis.com \ cloudbuild.googleapis.com
Uwaga: usługa Cloud Build zostanie wywołana przez polecenie gcloud functions deploy
i automatycznie skompiluje Twój kod do obrazu kontenera.
Pobieranie kodu źródłowego
W terminalu Cloud Shell uruchom te polecenia:
REPO_NAME="codelabs" REPO_URL="https://github.com/GoogleCloudPlatform/$REPO_NAME" SOURCE_DIR="cloud-functions-python-http" git clone --no-checkout --filter=blob:none --depth=1 $REPO_URL cd $REPO_NAME git sparse-checkout set $SOURCE_DIR git checkout cd $SOURCE_DIR
Sprawdź zawartość katalogu źródłowego:
ls
Potrzebujesz tych plików:
main.py python-powered.png test_main.py web_app.py
3. Przedstawiamy funkcje HTTP w Cloud Functions
Funkcje HTTP w Pythonie są zapisywane jako zwykłe funkcje w tym Pythonie. Funkcja musi akceptować pojedynczy argument flask.Request
, który zwykle ma nazwę request
.
main.py
import flask
def hello_world(request: flask.Request) -> flask.Response:
"""HTTP Cloud Function.
Returns:
- "Hello World! 👋"
"""
response = "Hello World! 👋"
return flask.Response(response, mimetype="text/plain")
# ...
Plik możesz otworzyć w wybranym edytorze wiersza poleceń (nano, vim lub emacs). Możesz go też otworzyć w edytorze Cloud Shell po ustawieniu katalogu źródłowego jako obszaru roboczego:
cloudshell open-workspace .
Wdróżmy tę funkcję jako funkcję HTTP w Cloud Functions za pomocą polecenia gcloud functions deploy
:
FUNCTION_NAME="hello_world" gcloud functions deploy $FUNCTION_NAME \ --runtime python312 \ --trigger-http \ --allow-unauthenticated
Wynik polecenia:
... Deploying function (may take a while - up to 2 minutes)...done. availableMemoryMb: 256 ... entryPoint: FUNCTION_NAME httpsTrigger: url: https://REGION-PROJECT_ID.cloudfunctions.net/FUNCTION_NAME ...
Uwagi na temat opcji gcloud functions deploy
:
--runtime
: określa środowisko wykonawcze języka. W przypadku Pythona mogą to być obecniepython37
,python38
,python39
,python310
lubpython312
. Zobacz Środowiska wykonawcze.--trigger-http
: do funkcji zostanie przypisany punkt końcowy. Żądania HTTP (POST, PUT, GET, DELETE i OPTIONS) wysyłane do punktu końcowego aktywują wykonanie funkcji.--allow-unauthenticated
: funkcja będzie publiczna i będzie mogła wykonywać wszystkie osoby wywołujące, bez sprawdzania uwierzytelniania.- Więcej informacji znajdziesz w artykule na temat gcloud Functions deploy.
Aby przetestować tę funkcję, możesz kliknąć adres URL httpsTrigger.url
wyświetlony w wynikach polecenia powyżej. Możesz też pobrać adres URL i wywołać funkcję za pomocą tych poleceń:
URL=$(gcloud functions describe $FUNCTION_NAME --format "value(httpsTrigger.url)") curl -w "\n" $URL
Powinien pojawić się następujący wynik:
Hello World! 👋
4. Jak pisać funkcję HTTP w Cloud Functions, która przyjmuje argumenty
Funkcje są bardziej uniwersalne, gdy akceptują argumenty. Zdefiniujmy nową funkcję hello_name
, która obsługuje parametr name
:
main.py
# ...
def hello_name(request: flask.Request) -> flask.Response:
"""HTTP Cloud Function.
Returns:
- "Hello {NAME}! 🚀" if "name=NAME" is defined in the GET request
- "Hello World! 🚀" otherwise
"""
name = request.args.get("name", "World")
response = f"Hello {name}! 🚀"
return flask.Response(response, mimetype="text/plain")
# ...
Wdróżmy tę nową funkcję:
FUNCTION_NAME="hello_name" gcloud functions deploy $FUNCTION_NAME \ --runtime python312 \ --trigger-http \ --allow-unauthenticated
Wynik polecenia:
... Deploying function (may take a while - up to 2 minutes)...done. availableMemoryMb: 256 ... entryPoint: FUNCTION_NAME httpsTrigger: url: https://REGION-PROJECT_ID.cloudfunctions.net/FUNCTION_NAME ...
Aby przetestować funkcję, możesz kliknąć adres URL httpsTrigger.url
wyświetlany w wynikach polecenia powyżej. Możesz też pobrać adres URL i wywołać funkcję za pomocą tych poleceń:
URL=$(gcloud functions describe $FUNCTION_NAME --format "value(httpsTrigger.url)") curl -w "\n" $URL
Powinien pojawić się domyślny wynik:
Hello World! 🚀
Otrzymujesz wynik domyślny, ponieważ argument name
nie jest ustawiony. Dodaj parametr do adresu URL:
curl -w "\n" $URL?name=YOUR%20NAME
Tym razem otrzymasz odpowiedź niestandardową:
Hello YOUR NAME! 🚀
Następnym krokiem jest dodanie testów jednostkowych, dzięki którym funkcje będą działać zgodnie z oczekiwaniami po zaktualizowaniu kodu źródłowego.
5. Testy pisania
Funkcje HTTP w Cloud Functions w Pythonie są testowane za pomocą modułu unittest
z biblioteki standardowej. Aby przetestować funkcję, nie musisz uruchamiać emulatora ani innej symulacji – wystarczy zwykły kod Pythona.
Tak wygląda test funkcji hello_world
i hello_name
:
test_main.py
import unittest
import unittest.mock
import main
class TestHello(unittest.TestCase):
def test_hello_world(self):
request = unittest.mock.Mock()
response = main.hello_world(request)
assert response.status_code == 200
assert response.get_data(as_text=True) == "Hello World! 👋"
def test_hello_name_no_name(self):
request = unittest.mock.Mock(args={})
response = main.hello_name(request)
assert response.status_code == 200
assert response.get_data(as_text=True) == "Hello World! 🚀"
def test_hello_name_with_name(self):
name = "FirstName LastName"
request = unittest.mock.Mock(args={"name": name})
response = main.hello_name(request)
assert response.status_code == 200
assert response.get_data(as_text=True) == f"Hello {name}! 🚀"
- Testy w języku Python zapisuje się w ten sam sposób co inne pliki tego typu. Zaczynają od zestawu operacji importu, a potem definiują klasy i funkcje.
- Deklaracja testu ma postać
class TestHello(TestCase)
. Musi to być klasa, która dziedziczy wartość z polaunittest.TestCase
. - Klasa testowa zawiera metody, z których każda musi zaczynać się od
test_
oznaczających poszczególne przypadki testowe. - Każdy przypadek testowy testuje jedną z naszych funkcji, naśladując parametr
request
(czyli zastępując go fałszywym obiektem danymi wymaganymi do testu). - Po wywołaniu każdej funkcji test sprawdza odpowiedź HTTP, by upewnić się, że jest zgodna z oczekiwaniami.
Ponieważ main.py
zależy od flask
, sprawdź, czy w środowisku testowym jest zainstalowana platforma Flask:
pip install flask
Zainstalowanie Flask daje wynik podobny do tego:
Collecting flask ... Successfully installed ... flask-3.0.2 ...
Przeprowadź te testy lokalnie:
python -m unittest
Te 3 testy jednostkowe powinny zakończyć się powodzeniem:
... ---------------------------------------------------------------------- Ran 3 tests in 0.001s OK
Następnie utwórz nową funkcję, która zwróci zapytanie „Python Powered”, logo.
6. Jak napisać „Python Powered” Funkcja HTTP w Cloud Functions
Chcemy, aby nowa funkcja była nieco ciekawsza, zwracając funkcję „Python Powered”. obraz do każdego żądania:
Poniższa lista zawiera kod, który to umożliwia:
main.py
# ...
def python_powered(request: flask.Request) -> flask.Response:
"""HTTP Cloud Function.
Returns:
- The official "Python Powered" logo
"""
return flask.send_file("python-powered.png")
Wdróż nową funkcję python_powered
:
FUNCTION_NAME="python_powered" gcloud functions deploy $FUNCTION_NAME \ --runtime python312 \ --trigger-http \ --allow-unauthenticated
Wynik polecenia:
... Deploying function (may take a while - up to 2 minutes)...done. availableMemoryMb: 256 ... entryPoint: FUNCTION_NAME httpsTrigger: url: https://REGION-PROJECT_ID.cloudfunctions.net/FUNCTION_NAME ...
Aby przetestować funkcję, kliknij adres URL httpsTrigger.url
wyświetlony w danych wyjściowych polecenia powyżej. Jeśli wszystko będzie działać prawidłowo, zobaczysz komunikat „Python Powered” na nowej karcie przeglądarki.
Następnie utworzysz aplikację, aby móc ją uruchomić i wypróbować lokalnie przed wdrożeniem.
7. Uruchamianie funkcji lokalnie
Funkcję HTTP można uruchomić lokalnie – wystarczy utworzyć aplikację internetową i wywołać funkcję w ramach trasy. Możesz go dodać w tym samym katalogu co Twoja funkcja. Plik o nazwie web_app.py
zawiera następującą treść:
web_app.py
import flask
import main
app = flask.Flask(__name__)
@app.get("/")
def index():
return main.python_powered(flask.request)
if __name__ == "__main__":
# Local development only
# Run "python web_app.py" and open http://localhost:8080
app.run(host="localhost", port=8080, debug=True)
- Ten plik tworzy aplikację Flask.
- Rejestruje trasę pod podstawowym adresem URL, która jest obsługiwana przez funkcję o nazwie
index()
. - Następnie funkcja
index()
wywołuje naszą funkcjępython_powered
, przekazując do niej bieżące żądanie.
Upewnij się, że w środowisku programistycznym zainstalowana jest platforma Flask:
pip install flask
Zainstalowanie Flask daje wynik podobny do tego:
Collecting flask ... Successfully installed ... flask-3.0.2 ...
Aby uruchomić tę aplikację lokalnie, uruchom to polecenie:
python web_app.py
Teraz skorzystaj z podglądu w przeglądarce Cloud Shell, aby przetestować aplikację internetową w przeglądarce. W Cloud Shell kliknij „Podgląd w przeglądarce”. i wybierz „Podejrzyj na porcie 8080”:
Cloud Shell otworzy adres URL umożliwiający podgląd w nowym oknie przeglądarki, korzystając z własnej usługi proxy. Podgląd w przeglądarce zezwala na dostęp przez HTTPS tylko do Twojego konta użytkownika. Jeśli wszystko działa prawidłowo, powinien wyświetlić się komunikat „Python Powered” logo.
8. Gratulacje!
Udało Ci się wdrożyć funkcje HTTP w Cloud Functions przy użyciu funkcji idiomatycznych, które obsługują żądania sieciowe za pomocą platformy Flask.
Cennik Cloud Functions zależy od tego, jak często jest wywoływana Twoja funkcja, w tym poziom bezpłatny dla funkcji, które rzadko się uruchamiają. Po zakończeniu testowania funkcji w Cloud Functions możesz je usunąć przy użyciu gcloud
:
gcloud functions delete hello_world --quiet gcloud functions delete hello_name --quiet gcloud functions delete python_powered --quiet
Możesz też usunąć funkcje z konsoli Google Cloud.
Mamy nadzieję, że podoba Ci się korzystanie z Cloud Functions w Pythonie.