1. Введение

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

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

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



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

Если вы запускаете Cloud Shell впервые, откроется экран с описанием этого инструмента. Нажмите Continue (Продолжить).

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

На этой виртуальной машине установлены все необходимые инструменты разработки. Она предлагает постоянный домашний каталог объемом 5 ГБ и работает в Google Cloud, что значительно повышает производительность сети и аутентификацию. Большую часть работы, если не всю, в этой практической работе можно выполнить в браузере.
После подключения к 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`
- Чтобы убедиться, что команда gcloud распознает ваш проект, выполните в Cloud Shell следующую команду:
gcloud config list project
Результат выполнения команды
[core] project = <PROJECT_ID>
Если нет, задайте его с помощью следующей команды:
gcloud config set project <PROJECT_ID>
Результат выполнения команды
Updated property [core/project].
Убедитесь, что Cloud Functions API и Cloud Build API включены
Чтобы убедиться, что Cloud Functions и Cloud Build API включены, выполните в Cloud Shell следующую команду:
gcloud services enable \ cloudfunctions.googleapis.com \ cloudbuild.googleapis.com
Примечание. Cloud Build будет вызван командой gcloud functions deploy и автоматически соберет ваш код в образ контейнера.
Скачайте исходный код
В терминале 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-функцию Cloud Functions с помощью команды 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 functions deploy…
Чтобы протестировать функцию, нажмите на URL httpsTrigger.url, который показан в результате выполнения команды выше. Вы также можете программно получить URL и вызвать функцию с помощью следующих команд:
URL=$(gcloud functions describe $FUNCTION_NAME --format "value(httpsTrigger.url)") curl -w "\n" $URL
Должен получиться следующий результат:
Hello World! 👋
4. Написание HTTP-функции Cloud Functions, которая принимает аргументы
Функции становятся более универсальными, когда они принимают аргументы. Давайте определим новую функцию 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_и представлять отдельный тестовый сценарий. - Каждый тестовый сценарий проверяет одну из наших функций, имитируя параметр
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-функции Cloud Functions на 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 нажмите кнопку Web Preview (Предварительный просмотр) и выберите Preview on port 8080 (Предварительный просмотр на порте 8080).

Приложение будет открыто в новой вкладке через прокси-сервер Cloud Shell. Доступ к веб-просмотру по протоколу 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.