1. Wprowadzenie

Python to popularny język programowania typu open source, którego używają m.in. badacze danych, deweloperzy aplikacji internetowych i administratorzy systemów.
Cloud Functions to bezserwerowa platforma obliczeniowa oparta na zdarzeniach. Cloud Functions pozwala pisać kod bez konieczności martwienia się o udostępnianie zasobów czy skalowanie w celu spełnienia zmieniających się wymagań.
Istnieją 2 typy funkcji w Cloud Functions:
- Funkcje HTTP odpowiadają na żądania HTTP. W tym ćwiczeniu utworzysz kilka takich funkcji.
- Funkcje działające w tle są aktywowane przez zdarzenia, takie jak opublikowanie wiadomości w Cloud Pub/Sub lub przesłanie pliku do Cloud Storage. Nie omawiamy tego w tym module, ale więcej informacji znajdziesz w dokumentacji.

To ćwiczenie praktyczne przeprowadzi Cię przez proces tworzenia własnych funkcji w Cloud Functions w Pythonie.
Co utworzysz
W tym ćwiczeniu opublikujesz funkcję w Cloud Functions, która po wywołaniu przez HTTP wyświetla logo „Python Powered”:

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 w Pythonie, 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 użyj istniejącego. Jeśli nie masz jeszcze konta Gmail lub Google Workspace, musisz je utworzyć.



- Nazwa projektu to wyświetlana nazwa dla uczestników tego projektu. Jest to ciąg znaków, który nie jest używany przez interfejsy API Google. Zawsze możesz go zaktualizować.
- Identyfikator projektu jest unikalny we wszystkich projektach Google Cloud i nie można go zmienić po ustawieniu. Konsola Cloud automatycznie generuje unikalny ciąg znaków, który zwykle nie ma znaczenia. W większości modułów codelabs musisz odwołać się do identyfikatora projektu (zwykle identyfikowanego jako
PROJECT_ID). Jeśli wygenerowany identyfikator Ci się nie podoba, możesz wygenerować inny losowy identyfikator. Możesz też spróbować użyć własnej nazwy i sprawdzić, czy jest dostępna. Nie można go zmienić po tym kroku i pozostaje on niezmieniony przez cały czas trwania projektu. - Dla Twojej informacji: istnieje trzecia wartość, numer projektu, której używają niektóre interfejsy API. Więcej informacji o tych 3 wartościach znajdziesz w dokumentacji.
- Następnie musisz włączyć płatności w konsoli Cloud, aby móc korzystać z zasobów i interfejsów API Google Cloud. Wykonanie tego ćwiczenia w programowaniu nie będzie kosztować dużo, jeśli w ogóle. Aby wyłączyć zasoby i uniknąć naliczania opłat po zakończeniu tego samouczka, możesz usunąć utworzone zasoby lub projekt. Nowi użytkownicy Google Cloud mogą skorzystać z bezpłatnego okresu próbnego, w którym mają do dyspozycji środki w wysokości 300 USD.
Uruchamianie Cloud Shell
Chociaż Google Cloud można obsługiwać zdalnie z laptopa, w tym ćwiczeniu będziesz używać Cloud Shell, czyli środowiska wiersza poleceń działającego w chmurze.
Aktywowanie Cloud Shell
- W konsoli Cloud kliknij Aktywuj Cloud Shell
.

Jeśli uruchamiasz Cloud Shell po raz pierwszy, zobaczysz ekran pośredni z opisem tego środowiska. W takim przypadku kliknij Dalej.

Uzyskanie dostępu do środowiska Cloud Shell i połączenie się z nim powinno zająć tylko kilka chwil.

Ta maszyna wirtualna zawiera wszystkie potrzebne narzędzia dla programistów. Zawiera również stały katalog domowy o pojemności 5 GB i działa w Google Cloud, co znacznie zwiększa wydajność sieci i usprawnia proces uwierzytelniania. Większość zadań w tym ćwiczeniu, a być może wszystkie, możesz wykonać w przeglądarce.
Po połączeniu z Cloud Shell zobaczysz, że uwierzytelnianie zostało już przeprowadzone, a projekt jest już ustawiony na Twój identyfikator projektu.
- Aby potwierdzić, że uwierzytelnianie zostało przeprowadzone, uruchom w Cloud Shell to polecenie:
gcloud auth list
Wynik polecenia
Credentialed Accounts
ACTIVE ACCOUNT
* <my_account>@<my_domain.com>
To set the active account, run:
$ gcloud config set account `ACCOUNT`
- Aby potwierdzić, że polecenie gcloud zna Twój projekt, uruchom w Cloud Shell to polecenie:
gcloud config list project
Wynik polecenia
[core] project = <PROJECT_ID>
Jeśli tak nie jest, możesz go ustawić za pomocą tego polecenia:
gcloud config set project <PROJECT_ID>
Wynik polecenia
Updated property [core/project].
Sprawdzanie, czy interfejsy Cloud Functions i Cloud Build API są włączone
Aby upewnić się, że interfejsy Cloud Functions i Cloud Build API są włączone, uruchom w Cloud Shell to polecenie:
gcloud services enable \ cloudfunctions.googleapis.com \ cloudbuild.googleapis.com
Uwaga: Cloud Build zostanie wywołany 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
Powinny być widoczne te pliki:
main.py python-powered.png test_main.py web_app.py
3. Wprowadzenie do funkcji HTTP w Cloud Functions
Funkcje HTTP w Cloud Functions w Pythonie są pisane jako zwykłe funkcje Pythona. 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")
# ...
Możesz otworzyć plik w preferowanym edytorze wiersza poleceń (nano, vim lub emacs). Możesz też otworzyć go 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 dotyczące opcji gcloud functions deploy:
--runtime: określa środowisko wykonawcze języka. W przypadku Pythona może to być obecniepython37,python38,python39,python310lubpython312. 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 będą wywoływać funkcję.--allow-unauthenticated: funkcja będzie publiczna, co pozwoli na dostęp wszystkim wywołującym bez sprawdzania uwierzytelniania.- Więcej informacji znajdziesz w artykule gcloud functions deploy.
Aby przetestować funkcję, możesz kliknąć adres URL httpsTrigger.url wyświetlany w wyniku polecenia powyżej. Możesz też pobrać adres URL automatycznie 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. Pisanie funkcji HTTP w Cloud Functions, która przyjmuje argumenty
Funkcje są bardziej wszechstronne, 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 wyniku polecenia powyżej. Możesz też pobrać adres URL automatycznie 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 niestandardową odpowiedź:
Hello YOUR NAME! 🚀
Następnym krokiem jest dodanie testów jednostkowych, aby mieć pewność, że funkcje będą działać zgodnie z oczekiwaniami po zaktualizowaniu kodu źródłowego.
5. Pisanie testów
Funkcje HTTP w Cloud Functions w Pythonie są testowane przy użyciu modułu unittest z biblioteki standardowej. Nie musisz uruchamiać emulatora ani innej symulacji, aby przetestować funkcję – wystarczy zwykły kod Pythona.
Oto jak 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 Pythonie są pisane w taki sam sposób jak inne pliki Pythona. Zaczynają się od zestawu importów, a następnie definiują klasy i funkcje.
- Deklaracja testu ma postać
class TestHello(TestCase). Musi to być klasa dziedzicząca zunittest.TestCase. - Klasa testowa zawiera metody, z których każda musi zaczynać się od
test_, które reprezentują poszczególne elementy testowania. - Każdy element testowania testuje jedną z naszych funkcji, symulując parametr
request(czyli zastępując go fałszywym obiektem z określonymi danymi wymaganymi do testu). - Po wywołaniu każdej funkcji test sprawdza odpowiedź HTTP, aby upewnić się, że jest ona zgodna z oczekiwaniami.
main.py zależy od flask, dlatego upewnij się, że w środowisku testowym jest zainstalowana platforma Flask:
pip install flask
Instalacja Flask wyświetli wynik podobny do tego:
Collecting flask ... Successfully installed ... flask-3.0.2 ...
Uruchom te testy lokalnie:
python -m unittest
Wszystkie 3 testy jednostkowe powinny zostać zaliczone:
... ---------------------------------------------------------------------- Ran 3 tests in 0.001s OK
Następnie utworzysz nową funkcję, która zwraca logo „Python Powered”.
6. Pisanie funkcji HTTP w Cloud Functions „Python Powered”
Sprawmy, aby nowa funkcja była nieco bardziej interesująca, zwracając obraz „Python Powered” w odpowiedzi na każde żądanie:

Poniżej znajdziesz 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świetlany w wynikach polecenia powyżej. Jeśli wszystko działa prawidłowo, na nowej karcie przeglądarki zobaczysz logo „Python Powered”.
Następnie utworzysz aplikację, aby móc uruchomić i wypróbować funkcję lokalnie przed wdrożeniem.
7. Lokalne uruchamianie funkcji
Możesz uruchomić funkcję HTTP lokalnie, tworząc aplikację internetową i wywołując funkcję w trasie. Możesz go dodać w tym samym katalogu co funkcja. Plik o nazwie web_app.py zawiera te informacje:
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 ona trasę pod podstawowym adresem URL, która jest obsługiwana przez funkcję o nazwie
index(). - Funkcja
index()wywołuje następnie funkcjępython_powered, przekazując jej bieżące żądanie.
Upewnij się, że w środowisku programistycznym jest zainstalowana platforma Flask:
pip install flask
Instalacja Flask wyświetli 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 użyj podglądu Cloud Shell w przeglądarce, aby przetestować aplikację internetową w przeglądarce. W Cloud Shell kliknij przycisk „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 pośredniczącej. Podgląd w przeglądarce ogranicza dostęp przez HTTPS tylko do Twojego konta użytkownika. Jeśli wszystko działa prawidłowo, powinno pojawić się logo „Python Powered”.

8. Gratulacje!

Udało Ci się wdrożyć funkcje HTTP w Cloud Functions, używając funkcji idiomatycznych, które obsługują żądania sieciowe za pomocą platformy Flask.
Ceny Cloud Functions zależą od tego, jak często funkcja jest wywoływana. W przypadku funkcji, które nie są często uruchamiane, dostępny jest poziom bezpłatny. Po zakończeniu testowania funkcji w Cloud Functions możesz je usunąć za pomocą gcloud:
gcloud functions delete hello_world --quiet gcloud functions delete hello_name --quiet gcloud functions delete python_powered --quiet
Funkcje możesz też usunąć w konsoli Google Cloud.
Mamy nadzieję, że korzystanie z Cloud Functions w Pythonie będzie dla Ciebie przyjemne.