1. Введение

Python — популярный язык программирования с открытым исходным кодом, используемый специалистами по анализу данных, разработчиками веб-приложений, системными администраторами и многими другими.
Cloud Functions — это событийно-ориентированная бессерверная вычислительная платформа. Cloud Functions позволяет писать код, не беспокоясь о выделении ресурсов или масштабировании для удовлетворения меняющихся требований.
Существует два типа облачных функций:
- Функции HTTP обрабатывают HTTP-запросы. В этом практическом занятии вы создадите несколько таких функций.
- Фоновые функции запускаются событиями, такими как публикация сообщения в Cloud Pub/Sub или загрузка файла в Cloud Storage . В этом практическом занятии мы это не рассматриваем, но вы можете узнать больше в документации .

В этом практическом занятии вы узнаете, как создать собственные облачные функции на Python.
Что вы построите
В этом практическом задании вы опубликуете облачную функцию, которая при вызове по протоколу HTTP отображает логотип "Python Powered" :

Что вы узнаете
- Как написать HTTP-функцию для облачных вычислений.
- Как написать HTTP-функцию для облачных вычислений, которая принимает аргументы.
- Как протестировать облачную HTTP-функцию.
- Как запустить локальный HTTP-сервер на Python, чтобы протестировать эту функцию.
- Как написать HTTP-функцию для облачных вычислений, которая возвращает изображение.
2. Настройка и требования
Настройка среды для самостоятельного обучения
- Войдите в консоль Google Cloud и создайте новый проект или используйте существующий. Если у вас еще нет учетной записи Gmail или Google Workspace, вам необходимо ее создать .



- Название проекта — это отображаемое имя участников данного проекта. Это строка символов, не используемая API Google. Вы всегда можете его изменить.
- Идентификатор проекта уникален для всех проектов Google Cloud и является неизменяемым (его нельзя изменить после установки). Консоль Cloud автоматически генерирует уникальную строку; обычно вам неважно, какая она. В большинстве практических заданий вам потребуется указать идентификатор вашего проекта (обычно обозначается как
PROJECT_ID). Если сгенерированный идентификатор вас не устраивает, вы можете сгенерировать другой случайный идентификатор. В качестве альтернативы вы можете попробовать свой собственный и посмотреть, доступен ли он. После этого шага его нельзя изменить, и он сохраняется на протяжении всего проекта. - К вашему сведению, существует третье значение — номер проекта , которое используется некоторыми API. Подробнее обо всех трех значениях можно узнать в документации .
- Далее вам потребуется включить оплату в консоли Cloud для использования ресурсов/API Cloud. Выполнение этого практического задания не потребует больших затрат, если вообще потребует. Чтобы отключить ресурсы и избежать дополнительных расходов после завершения этого урока, вы можете удалить созданные ресурсы или удалить проект. Новые пользователи Google Cloud имеют право на бесплатную пробную версию стоимостью 300 долларов США .
Запустить Cloud Shell
Хотя Google Cloud можно управлять удаленно с ноутбука, в этом практическом занятии вы будете использовать Cloud Shell — среду командной строки, работающую в облаке.
Активировать Cloud Shell
- В консоли Cloud нажмите «Активировать Cloud Shell» .
.

Если вы запускаете Cloud Shell впервые, вам будет показан промежуточный экран с описанием его возможностей. Если вам был показан промежуточный экран, нажмите «Продолжить» .

Подготовка и подключение к Cloud Shell займут всего несколько минут.

Эта виртуальная машина оснащена всеми необходимыми инструментами разработки. Она предоставляет постоянный домашний каталог объемом 5 ГБ и работает в облаке Google, что значительно повышает производительность сети и аутентификацию. Большая часть, если не вся, ваша работа в этом практическом задании может быть выполнена с помощью браузера.
После подключения к Cloud Shell вы увидите, что прошли аутентификацию и что проект настроен на ваш идентификатор проекта.
- Выполните следующую команду в Cloud Shell, чтобы подтвердить свою аутентификацию:
gcloud auth list
вывод команды
Credentialed Accounts
ACTIVE ACCOUNT
* <my_account>@<my_domain.com>
To set the active account, run:
$ gcloud config set account `ACCOUNT`
- Выполните следующую команду в Cloud Shell, чтобы убедиться, что команда gcloud знает о вашем проекте:
gcloud config list project
вывод команды
[core] project = <PROJECT_ID>
Если это не так, вы можете установить это с помощью следующей команды:
gcloud config set project <PROJECT_ID>
вывод команды
Updated property [core/project].
Убедитесь, что API Cloud Functions и Cloud Build включены.
Выполните следующую команду в Cloud Shell, чтобы убедиться, что API Cloud Functions и Cloud Build включены:
gcloud services enable \ cloudfunctions.googleapis.com \ cloudbuild.googleapis.com
Примечание: команда gcloud functions deploy будет вызывать Cloud Build и автоматически скомпилирует ваш код в образ контейнера.
Скачать исходный код
В терминале Cloud Shell выполните следующие команды:
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
Ознакомьтесь с содержимым исходного каталога:
ls
У вас должны быть следующие файлы:
main.py python-powered.png test_main.py web_app.py
3. Представляем HTTP Cloud Functions
HTTP-функции Cloud Functions в Python пишутся как обычные функции Python. Функция должна принимать один аргумент flask.Request , который обычно называется 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")
# ...
Вы можете открыть файл с помощью предпочитаемого вами редактора командной строки (nano, vim или emacs). Вы также можете открыть его в редакторе Cloud Shell, предварительно указав исходный каталог в качестве рабочей области:
cloudshell open-workspace .
Давайте развернем эту функцию как HTTP-облачную функцию, используя команду gcloud functions deploy :
FUNCTION_NAME="hello_world" gcloud functions deploy $FUNCTION_NAME \ --runtime python312 \ --trigger-http \ --allow-unauthenticated
Вывод команды:
... 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 ...
Примечания к параметрам gcloud functions deploy :
-
--runtime: Этот параметр задает среду выполнения языка. Для Python в настоящее время это может бытьpython37,python38,python39,python310илиpython312. См. раздел «Среды выполнения» . -
--trigger-http: Функциональности будет назначена конечная точка. HTTP-запросы (POST, PUT, GET, DELETE и OPTIONS) к этой конечной точке будут запускать выполнение функции. -
--allow-unauthenticated: Функция будет общедоступной, что позволит всем вызывающим её пользователям не проверять аутентификацию. - Для получения более подробной информации см. раздел "Развертывание функций gcloud" .
Для проверки функции вы можете щелкнуть по URL-адресу httpsTrigger.url отображаемому в выводе команды выше. Вы также можете программно получить этот URL-адрес и вызвать функцию с помощью следующих команд:
URL=$(gcloud functions describe $FUNCTION_NAME --format "value(httpsTrigger.url)") curl -w "\n" $URL
В результате вы должны получить следующее:
Hello World! 👋
4. Написание HTTP-функции Cloud Function, принимающей аргументы.
Функции становятся более универсальными, когда принимают аргументы. Давайте определим новую функцию hello_name , которая поддерживает параметр 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")
# ...
Давайте развернем эту новую функцию:
FUNCTION_NAME="hello_name" gcloud functions deploy $FUNCTION_NAME \ --runtime python312 \ --trigger-http \ --allow-unauthenticated
Вывод команды:
... 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 ...
Для проверки функции вы можете щелкнуть по URL-адресу httpsTrigger.url отображаемому в выводе команды выше. Вы также можете программно получить этот URL-адрес и вызвать функцию с помощью следующих команд:
URL=$(gcloud functions describe $FUNCTION_NAME --format "value(httpsTrigger.url)") curl -w "\n" $URL
Вы должны получить результат по умолчанию:
Hello World! 🚀
Вы получаете результат по умолчанию, потому что аргумент name не задан. Добавьте параметр к URL:
curl -w "\n" $URL?name=YOUR%20NAME
На этот раз вы получите свой собственный ответ:
Hello YOUR NAME! 🚀
Следующий шаг — добавление модульных тестов, чтобы убедиться, что ваши функции продолжают работать должным образом при обновлении исходного кода.
5. Письменные тесты
Функции HTTP Cloud Functions в Python тестируются с помощью модуля unittest из стандартной библиотеки. Нет необходимости запускать эмулятор или другую симуляцию для тестирования вашей функции — достаточно обычного кода Python.
Вот как выглядит тест для функций hello_world и 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}! 🚀"
- Тесты в Python пишутся так же, как и другие файлы Python. Начинается всё с набора импортов, затем определяются классы и функции.
- Объявление теста имеет вид
class TestHello(TestCase). Это должен быть класс, наследующий отunittest.TestCase. - В классе test есть методы, каждый из которых должен начинаться с
test_, представляющего собой отдельный тестовый случай. - Каждый тестовый случай проверяет одну из наших функций, имитируя параметр
request(то есть заменяя его фиктивным объектом со специфическими данными, необходимыми для теста). - После вызова каждой функции тест проверяет HTTP-ответ, чтобы убедиться, что он соответствует нашим ожиданиям.
Поскольку main.py зависит от flask , убедитесь, что фреймворк Flask установлен в вашей тестовой среде:
pip install flask
Установка Flask выдаёт результат, аналогичный следующему:
Collecting flask ... Successfully installed ... flask-3.0.2 ...
Запустите эти тесты локально:
python -m unittest
Все три модульных теста должны пройти успешно:
... ---------------------------------------------------------------------- Ran 3 tests in 0.001s OK
Далее вам нужно будет создать новую функцию, которая будет возвращать логотип "Python Powered".
6. Написание облачной HTTP-функции на основе Python.
Давайте сделаем новую функцию немного интереснее, возвращая изображение "Python Powered" для каждого запроса:

В следующем фрагменте кода показано, как это реализовать:
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")
Разверните новую функцию python_powered :
FUNCTION_NAME="python_powered" gcloud functions deploy $FUNCTION_NAME \ --runtime python312 \ --trigger-http \ --allow-unauthenticated
Вывод команды:
... 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 ...
Чтобы проверить работу функции, щелкните по URL-адресу httpsTrigger.url указанному в выводе команды выше. Если все работает правильно, вы увидите логотип "Python Powered" в новой вкладке браузера!
Далее вам нужно будет создать приложение, чтобы вы могли запустить и протестировать свою функцию локально перед развертыванием.
7. Запуск функции локально
Вы можете запустить HTTP-функцию локально, создав веб-приложение и вызвав его в маршруте. Его можно добавить в ту же директорию, что и вашу функцию. Файл web_app.py содержит следующее:
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)
- Этот файл создает приложение Flask.
- Он регистрирует маршрут по базовому URL-адресу, обработка которого осуществляется с помощью функции с именем
index(). - Затем функция
index()вызывает нашу функциюpython_powered, передавая ей текущий запрос.
Убедитесь, что фреймворк Flask установлен в вашей среде разработки:
pip install flask
Установка Flask выдаёт результат, аналогичный следующему:
Collecting flask ... Successfully installed ... flask-3.0.2 ...
Для запуска этого приложения локально выполните следующую команду:
python web_app.py
Теперь воспользуйтесь функцией предварительного просмотра веб-приложения в Cloud Shell, чтобы протестировать веб-приложение в браузере. В Cloud Shell нажмите кнопку «Предварительный просмотр веб-приложения» и выберите «Предварительный просмотр на порту 8080»:

Cloud Shell открывает URL-адрес предварительного просмотра на своем прокси-сервисе в новом окне браузера. Веб-предварительный просмотр ограничивает доступ по протоколу HTTPS только вашей учетной записью пользователя. Если все работает правильно, вы должны увидеть логотип "Python Powered"!

8. Поздравляем!

Вы развернули HTTP Cloud Functions, используя идиоматические функции, обрабатывающие веб-запросы с помощью фреймворка Flask.
Стоимость Cloud Functions зависит от частоты вызова вашей функции, включая бесплатный уровень для функций, которые запускаются нечасто. После завершения тестирования Cloud Functions вы можете удалить их с помощью gcloud :
gcloud functions delete hello_world --quiet gcloud functions delete hello_name --quiet gcloud functions delete python_powered --quiet
Вы также можете удалить эти функции через консоль Google Cloud .
Надеемся, вам понравится использовать Cloud Functions в Python!