Zara  Bryant

Zara Bryant

1682736406

Writing Python Web Apps with VS Code

Writing Python Web Apps with VS Code

Pamela will share her tips for using VS Code to develop Python web apps using frameworks like Django, Flask, or FastAPI. We'll set up a Dev Container to create a full local development environment (including PostgreSQL), install VS Code extensions for linting and formatting, and configure launch.json to help us debug the web application routes. At the end, when all is working well, we'll deploy it to Azure.

#python #vscode #webapp #django #flask #fastapi 

Writing Python Web Apps with VS Code

Как выполнять асинхронные задачи с помощью FastAPI и Celery

Если длительный процесс является частью рабочего процесса вашего приложения, а не блокирует ответ, вы должны обрабатывать его в фоновом режиме, вне обычного потока запросов/ответов.

Возможно, ваше веб-приложение требует, чтобы пользователи отправляли эскиз (который, вероятно, нужно будет изменить в размере) и подтверждали свой адрес электронной почты при регистрации. Если ваше приложение обработает изображение и отправит электронное письмо с подтверждением непосредственно в обработчике запросов, то конечному пользователю придется без необходимости ждать, пока они оба закончат обработку, прежде чем страница загрузится или обновится. Вместо этого вы захотите передать эти процессы в очередь задач и позволить отдельному рабочему процессу справиться с ними, чтобы вы могли немедленно отправить ответ обратно клиенту. Затем конечный пользователь может выполнять другие действия на стороне клиента, пока происходит обработка. Ваше приложение также может свободно отвечать на запросы других пользователей и клиентов.

Для этого мы проведем вас через процесс установки и настройки Celery и Redis для обработки длительных процессов в приложении FastAPI. Мы также будем использовать Docker и Docker Compose, чтобы связать все вместе. Наконец, мы рассмотрим, как тестировать задачи Celery с помощью модульных и интеграционных тестов.

Цели

К концу этого урока вы сможете:

  1. Интегрируйте Celery в приложение FastAPI и создавайте задачи.
  2. Контейнеризируйте FastAPI, Celery и Redis с помощью Docker.
  3. Запуск процессов в фоновом режиме с отдельным рабочим процессом.
  4. Сохраните журналы Celery в файл.
  5. Настройте Flower для мониторинга и управления заданиями и работниками Celery.
  6. Протестируйте задачу Celery с помощью модульных и интеграционных тестов.

Фоновые задачи

Опять же, чтобы улучшить взаимодействие с пользователем, длительные процессы должны выполняться вне обычного потока HTTP-запросов/ответов, в фоновом процессе.

Примеры:

  1. Запуск моделей машинного обучения
  2. Отправка писем с подтверждением
  3. Веб-скрапинг и сканирование
  4. Анализ данных
  5. Обработка изображений
  6. Генерация отчетов

При создании приложения старайтесь отличать задачи, которые должны выполняться в течение жизненного цикла запроса/ответа, например операции CRUD, от тех, которые должны выполняться в фоновом режиме.

Стоит отметить, что вы можете использовать класс BackgroundTasks FastAPI, который исходит непосредственно от Starlette , для запуска задач в фоновом режиме.

Например:

from fastapi import BackgroundTasks


def send_email(email, message):
    pass


@app.get("/")
async def ping(background_tasks: BackgroundTasks):
    background_tasks.add_task(send_email, "email@address.com", "Hi!")
    return {"message": "pong!"}

Итак, когда вы должны использовать Celery вместо BackgroundTasks?

  1. Задачи с интенсивным использованием ЦП : Celery следует использовать для задач, выполняющих тяжелые фоновые вычисления, поскольку BackgroundTasksони выполняются в том же цикле обработки событий, который обслуживает запросы вашего приложения.
  2. Очередь задач: если вам требуется очередь задач для управления задачами и рабочими, вам следует использовать Celery. Часто вам нужно получить статус задания, а затем выполнить какое-либо действие на основе статуса, например отправить электронное письмо об ошибке, запустить другую фоновую задачу или повторить задачу. Celery управляет всем этим за вас.

Рабочий процесс

Наша цель — разработать приложение FastAPI, которое работает вместе с Celery для обработки длительных процессов, выходящих за рамки обычного цикла запроса/ответа.

  1. Конечный пользователь запускает новую задачу через POST-запрос на стороне сервера.
  2. В обработчике маршрута задача добавляется в очередь, а идентификатор задачи отправляется обратно на сторону клиента.
  3. Используя AJAX, клиент продолжает опрашивать сервер, чтобы проверить статус задачи, в то время как сама задача выполняется в фоновом режиме.

пользовательский поток очереди fastapi и сельдерея

Настройка проекта

Клонируйте базовый проект из репозитория fastapi-celery , а затем проверьте тег v1 в основной ветке:

$ git clone https://github.com/testdrivenio/fastapi-celery --branch v1 --single-branch
$ cd fastapi-celery
$ git checkout v1 -b master

Поскольку нам нужно будет управлять всего тремя процессами (FastAPI, Redis, Celery worker), мы будем использовать Docker, чтобы упростить наш рабочий процесс, подключив их так, чтобы их можно было запускать из одного окна терминала с помощью одной команды.

В корне проекта создайте образы и разверните контейнеры Docker:

$ docker-compose up -d --build

После завершения сборки перейдите по адресу http://localhost:8004 :

быстрый проект

Убедитесь, что тесты также проходят:

$ docker-compose exec web python -m pytest

=============================== test session starts ================================
platform linux -- Python 3.11.2, pytest-7.2.2, pluggy-1.0.0
rootdir: /usr/src/app
plugins: anyio-3.6.2
collected 1 item

tests/test_tasks.py .                                                        [100%]

================================ 1 passed in 0.20s =================================

Прежде чем двигаться дальше, взгляните на структуру проекта:

├── .gitignore
├── LICENSE
├── README.md
├── docker-compose.yml
└── project
    ├── Dockerfile
    ├── main.py
    ├── requirements.txt
    ├── static
    │   ├── main.css
    │   └── main.js
    ├── templates
    │   ├── _base.html
    │   ├── footer.html
    │   └── home.html
    └── tests
        ├── __init__.py
        ├── conftest.py
        └── test_tasks.py

Запустить задачу

onclickВ файле project/templates/home.html настроен обработчик событий, который прослушивает нажатие кнопки :

<div class="btn-group" role="group" aria-label="Basic example">
  <button type="button" class="btn btn-primary" onclick="handleClick(1)">Short</a>
  <button type="button" class="btn btn-primary" onclick="handleClick(2)">Medium</a>
  <button type="button" class="btn btn-primary" onclick="handleClick(3)">Long</a>
</div>

onclickвызовы handleClick, найденные в project/static/main.js , которые отправляют запрос AJAX POST на сервер с соответствующим типом задачи: 1, 2, или 3.

function handleClick(type) {
  fetch('/tasks', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ type: type }),
  })
  .then(response => response.json())
  .then(res => getStatus(res.data.task_id));
}

На стороне сервера уже настроен маршрут для обработки запроса в project/main.py :

@app.post("/tasks", status_code=201)
def run_task(payload = Body(...)):
    task_type = payload["type"]
    return JSONResponse(task_type)

Теперь самое интересное — подключение Celery!

Настройка сельдерея

Начните с добавления Celery и Redis в файл requirements.txt :

aiofiles==23.1.0
celery==5.2.7
fastapi==0.95.0
Jinja2==3.1.2
pytest==7.2.2
redis==4.5.4
requests==2.28.2
uvicorn==0.21.1
httpx==0.23.3

Celery использует брокер сообщений — RabbitMQ , Redis или AWS Simple Queue Service (SQS) — для облегчения связи между исполнителем Celery и веб-приложением. Сообщения добавляются в брокер, которые затем обрабатываются исполнителями. После этого результаты добавляются в бэкэнд.

Redis будет использоваться как в качестве брокера, так и в качестве серверной части. Добавьте Redis и рабочий процесс Celery в файл docker-compose.yml следующим образом:

version: '3.8'

services:

  web:
    build: ./project
    ports:
      - 8004:8000
    command: uvicorn main:app --host 0.0.0.0 --reload
    volumes:
      - ./project:/usr/src/app
    environment:
      - CELERY_BROKER_URL=redis://redis:6379/0
      - CELERY_RESULT_BACKEND=redis://redis:6379/0
    depends_on:
      - redis

  worker:
    build: ./project
    command: celery -A worker.celery worker --loglevel=info
    volumes:
      - ./project:/usr/src/app
    environment:
      - CELERY_BROKER_URL=redis://redis:6379/0
      - CELERY_RESULT_BACKEND=redis://redis:6379/0
    depends_on:
      - web
      - redis

  redis:
    image: redis:7

Обратите внимание на celery -A worker.celery worker --loglevel=info:

  1. celery workerиспользуется для запуска работника Celery
  2. -A worker.celeryзапускает приложение Celery (которое мы вскоре определим)
  3. --loglevel=infoустанавливает уровень ведения журнала для информации

Затем создайте новый файл с именем worker.py в «проекте»:

import os
import time

from celery import Celery


celery = Celery(__name__)
celery.conf.broker_url = os.environ.get("CELERY_BROKER_URL", "redis://localhost:6379")
celery.conf.result_backend = os.environ.get("CELERY_RESULT_BACKEND", "redis://localhost:6379")


@celery.task(name="create_task")
def create_task(task_type):
    time.sleep(int(task_type) * 10)
    return True

Здесь мы создали новый экземпляр Celery и с помощью декоратора задач определили новую функцию задачи Celery с именем create_task.

Имейте в виду, что сама задача будет выполняться воркером Celery.

Запустить задачу

Обновите обработчик маршрута в main.py , чтобы запустить задачу и ответить идентификатором задачи:

@app.post("/tasks", status_code=201)
def run_task(payload = Body(...)):
    task_type = payload["type"]
    task = create_task.delay(int(task_type))
    return JSONResponse({"task_id": task.id})

Не забудьте импортировать задачу:

from worker import create_task

Соберите образы и запустите новые контейнеры:

$ docker-compose up -d --build

Чтобы запустить новую задачу, запустите:

$ curl http://localhost:8004/tasks -H "Content-Type: application/json" --data '{"type": 0}'

Вы должны увидеть что-то вроде:

{
  "task_id": "14049663-6257-4a1f-81e5-563c714e90af"
}

Статус задачи

Вернитесь к handleClickфункции на стороне клиента:

function handleClick(type) {
  fetch('/tasks', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ type: type }),
  })
  .then(response => response.json())
  .then(res => getStatus(res.data.task_id));
}

Когда ответ исходного запроса AJAX возвращается, мы продолжаем вызывать getStatus()идентификатор задачи каждую секунду:

function getStatus(taskID) {
  fetch(`/tasks/${taskID}`, {
    method: 'GET',
    headers: {
      'Content-Type': 'application/json'
    },
  })
  .then(response => response.json())
  .then(res => {
    const html = `
      <tr>
        <td>${taskID}</td>
        <td>${res.data.task_status}</td>
        <td>${res.data.task_result}</td>
      </tr>`;
    document.getElementById('tasks').prepend(html);
    const newRow = document.getElementById('table').insertRow();
    newRow.innerHTML = html;
    const taskStatus = res.data.task_status;
    if (taskStatus === 'finished' || taskStatus === 'failed') return false;
    setTimeout(function() {
      getStatus(res.data.task_id);
    }, 1000);
  })
  .catch(err => console.log(err));
}

Если ответ успешен, в таблицу DOM добавляется новая строка.

Обновите get_statusобработчик маршрута, чтобы вернуть статус:

@app.get("/tasks/{task_id}")
def get_status(task_id):
    task_result = AsyncResult(task_id)
    result = {
        "task_id": task_id,
        "task_status": task_result.status,
        "task_result": task_result.result
    }
    return JSONResponse(result)

Импортировать асинхронный результат :

from celery.result import AsyncResult

Обновите контейнеры:

$ docker-compose up -d --build

Активировать новую задачу:

$ curl http://localhost:8004/tasks -H "Content-Type: application/json" --data '{"type": 1}'

Затем возьмите task_idиз ответа и вызовите обновленную конечную точку, чтобы просмотреть статус:

$ curl http://localhost:8004/tasks/f3ae36f1-58b8-4c2b-bf5b-739c80e9d7ff

{
  "task_id": "455234e0-f0ea-4a39-bbe9-e3947e248503",
  "task_result": true,
  "task_status": "SUCCESS"
}

Также проверьте это в браузере:

fastapi, сельдерей, докер

Журналы сельдерея

Обновите workerслужбу в docker-compose.yml , чтобы журналы Celery выгружались в файл журнала:

worker:
  build: ./project
  command: celery -A worker.celery worker --loglevel=info --logfile=logs/celery.log
  volumes:
    - ./project:/usr/src/app
  environment:
    - CELERY_BROKER_URL=redis://redis:6379/0
    - CELERY_RESULT_BACKEND=redis://redis:6379/0
  depends_on:
    - web
    - redis

Добавьте новый каталог в «проект» с именем «logs». Затем добавьте новый файл с именем celery.log в этот вновь созданный каталог.

Обновлять:

$ docker-compose up -d --build

Вы должны увидеть, что файл журнала заполняется локально, так как мы настроили том:

[2023-04-05 16:10:33,257: INFO/MainProcess] Connected to redis://redis:6379/0
[2023-04-05 16:10:33,262: INFO/MainProcess] mingle: searching for neighbors
[2023-04-05 16:10:34,271: INFO/MainProcess] mingle: all alone
[2023-04-05 16:10:34,283: INFO/MainProcess] celery@6ea5007507db ready.
[2023-04-05 16:11:49,400: INFO/MainProcess]
  Task create_task[7f0022ec-bcc8-4eff-b825-bde60d15f824] received
[2023-04-05 16:11:59,418: INFO/ForkPoolWorker-7]
  Task create_task[7f0022ec-bcc8-4eff-b825-bde60d15f824]
  succeeded in 10.015363933052868s: True

Цветочная приборная панель

Flower — это легкий веб-инструмент для мониторинга Celery в режиме реального времени. Вы можете отслеживать текущие задачи, увеличивать или уменьшать рабочий пул, просматривать графики и ряд статистических данных, и это лишь некоторые из них.

Добавьте его в файл requirements.txt :

aiofiles==23.1.0
celery==5.2.7
fastapi==0.95.0
flower==1.2.0
Jinja2==3.1.2
pytest==7.2.2
redis==4.5.4
requests==2.28.2
uvicorn==0.21.1
httpx==0.23.3

Затем добавьте новый сервис в docker-compose.yml :

dashboard:
  build: ./project
  command: celery --broker=redis://redis:6379/0 flower --port=5555
  ports:
    - 5556:5555
  environment:
    - CELERY_BROKER_URL=redis://redis:6379/0
    - CELERY_RESULT_BACKEND=redis://redis:6379/0
  depends_on:
    - web
    - redis
    - worker

Проверьте это:

$ docker-compose up -d --build

Перейдите по адресу http://localhost:5556 , чтобы просмотреть панель управления. Вы должны увидеть одного рабочего, готового к работе:

цветочная приборная панель

Запустите еще несколько задач, чтобы полностью протестировать панель инструментов:

цветочная приборная панель

Попробуйте добавить еще несколько рабочих, чтобы увидеть, как это повлияет на ситуацию:

$ docker-compose up -d --build --scale worker=3

Тесты

Начнем с самого простого теста:

def test_task():
    assert create_task.run(1)
    assert create_task.run(2)
    assert create_task.run(3)

Добавьте приведенный выше тестовый пример в project/tests/test_tasks.py , а затем добавьте следующий импорт:

from worker import create_task

Запустите этот тест по отдельности:

$ docker-compose exec web python -m pytest -k "test_task and not test_home"

Выполнение должно занять около одной минуты:

=============================== test session starts ================================
platform linux -- Python 3.11.2, pytest-7.2.2, pluggy-1.0.0
rootdir: /usr/src/app, configfile: pytest.ini
plugins: anyio-3.6.2
collected 2 items / 1 deselected / 1 selected

tests/test_tasks.py .                                                        [100%]

==================== 1 passed, 1 deselected in 60.07s (0:01:00) ====================

Стоит отметить, что в приведенных выше утверждениях мы использовали метод .run(а не .delay) для запуска задачи напрямую без работника Celery.

Хотите поиздеваться над .runметодом, чтобы ускорить процесс?

@patch("worker.create_task.run")
def test_mock_task(mock_run):
    assert create_task.run(1)
    create_task.run.assert_called_once_with(1)

    assert create_task.run(2)
    assert create_task.run.call_count == 2

    assert create_task.run(3)
    assert create_task.run.call_count == 3

Импорт:

from unittest.mock import patch

Тест:

$ docker-compose exec web python -m pytest -k "test_mock_task"

=============================== test session starts ================================
platform linux -- Python 3.11.2, pytest-7.2.2, pluggy-1.0.0
rootdir: /usr/src/app, configfile: pytest.ini
plugins: anyio-3.6.2
collected 2 items / 1 deselected / 1 selected

tests/test_tasks.py .                                                        [100%]

========================= 1 passed, 1 deselected in 0.10s ==========================

Гораздо быстрее!

Как насчет полного интеграционного теста?

def test_task_status(test_app):
    response = test_app.post(
        "/tasks",
        data=json.dumps({"type": 1})
    )
    content = response.json()
    task_id = content["task_id"]
    assert task_id

    response = test_app.get(f"tasks/{task_id}")
    content = response.json()
    assert content == {"task_id": task_id, "task_status": "PENDING", "task_result": None}
    assert response.status_code == 200

    while content["task_status"] == "PENDING":
        response = test_app.get(f"tasks/{task_id}")
        content = response.json()
    assert content == {"task_id": task_id, "task_status": "SUCCESS", "task_result": True}

Имейте в виду, что в этом тесте используется тот же брокер и серверная часть, что и при разработке. Возможно, вы захотите создать новое приложение Celery для тестирования.

Добавьте импорт:

import json

Убедитесь, что тест проходит.

Заключение

Это базовое руководство по настройке Celery для запуска длительных задач в приложении FastAPI. Вы должны позволить очереди обрабатывать любые процессы, которые могут блокировать или замедлять работу пользовательского кода.

Celery также можно использовать для выполнения повторяющихся задач и разделения сложных, ресурсоемких задач, чтобы вычислительную нагрузку можно было распределить между несколькими машинами, чтобы сократить (1) время выполнения и (2) нагрузку на обработку машины. клиентские запросы.

Наконец, если вам интересно, как использовать WebSockets для проверки состояния задачи Celery вместо использования опроса AJAX, ознакомьтесь с курсом The Definitive Guide to Celery и FastAPI .

Возьмите код из репозитория .

Оригинальный источник статьи: https://testdriven.io/

#fastapi #celery #tasks 

Как выполнять асинхронные задачи с помощью FastAPI и Celery
津田  淳

津田 淳

1680851100

如何使用 FastAPI 和 Celery 执行异步任务

如果一个长时间运行的进程是应用程序工作流的一部分,而不是阻塞响应,您应该在后台处理它,在正常的请求/响应流之外。

也许您的 Web 应用程序要求用户提交缩略图(可能需要重新调整大小)并在注册时确认他们的电子邮件。如果您的应用程序处理图像并直接在请求处理程序中发送确认电子邮件,那么最终用户将不得不在页面加载或更新之前不必要地等待它们完成处理。相反,您需要将这些进程传递给任务队列并让一个单独的工作进程处理它,这样您就可以立即将响应发送回客户端。然后,最终用户可以在处理过程中在客户端做其他事情。您的应用程序也可以自由响应来自其他用户和客户的请求。

为实现这一目标,我们将引导您完成设置和配置Celery和 Redis的过程,以处理 FastAPI 应用程序中长时间运行的进程。我们还将使用 Docker 和 Docker Compose 将所有内容联系在一起。最后,我们将了解如何使用单元测试和集成测试来测试 Celery 任务。

目标

在本教程结束时,您将能够:

  1. 将 Celery 集成到 FastAPI 应用程序中并创建任务。
  2. 使用 Docker 容器化 FastAPI、Celery 和 Redis。
  3. 使用单独的工作进程在后台运行进程。
  4. 将 Celery 日志保存到文件中。
  5. 设置Flower以监视和管理 Celery 作业和工人。
  6. 使用单元测试和集成测试测试 Celery 任务。

后台任务

同样,为了改善用户体验,长时间运行的进程应该在正常的 HTTP 请求/响应流之外的后台进程中运行。

例子:

  1. 运行机器学习模型
  2. 发送确认邮件
  3. 网页抓取和抓取
  4. 分析数据
  5. 处理图像
  6. 生成报告

在构建应用程序时,请尝试区分应在请求/响应生命周期内运行的任务(如 CRUD 操作)与应在后台运行的任务。

值得注意的是,您可以利用直接来自Starlette的 FastAPI 的BackgroundTasks类在后台运行任务。

例如:

from fastapi import BackgroundTasks


def send_email(email, message):
    pass


@app.get("/")
async def ping(background_tasks: BackgroundTasks):
    background_tasks.add_task(send_email, "email@address.com", "Hi!")
    return {"message": "pong!"}

那么,什么时候应该使用 Celery 而不是BackgroundTasks

  1. CPU 密集型任务:Celery 应该用于执行大量后台计算的任务,因为它BackgroundTasks在为您的应用请求提供服务的同一事件循环中运行。
  2. 任务队列:如果你需要一个任务队列来管理任务和工作人员,你应该使用 Celery。通常您会想要检索作业的状态,然后根据状态执行一些操作——例如,发送错误电子邮件、启动不同的后台任务或重试任务。Celery 为你管理这一切。

工作流程

我们的目标是开发一个与 Celery 一起工作的 FastAPI 应用程序,以处理正常请求/响应周期之外的长时间运行的进程。

  1. 最终用户通过向服务器端发送 POST 请求来启动新任务。
  2. 在路由处理程序中,任务被添加到队列中,任务 ID 被发送回客户端。
  3. 使用 AJAX,当任务本身在后台运行时,客户端继续轮询服务器以检查任务的状态。

fastapi 和 celery 队列用户流程

项目设置

从fastapi-celery repo克隆基础项目,然后将v1标签检出到 master 分支:

$ git clone https://github.com/testdrivenio/fastapi-celery --branch v1 --single-branch
$ cd fastapi-celery
$ git checkout v1 -b master

由于我们总共需要管理三个进程(FastAPI、Redis、Celery worker),我们将使用 Docker 来简化我们的工作流程,方法是将它们连接起来,以便它们都可以从一个终端窗口使用一个命令运行。

从项目根目录,创建图像并启动 Docker 容器:

$ docker-compose up -d --build

构建完成后,导航到http://localhost:8004

fastapi项目

确保测试也通过:

$ docker-compose exec web python -m pytest

=============================== test session starts ================================
platform linux -- Python 3.11.2, pytest-7.2.2, pluggy-1.0.0
rootdir: /usr/src/app
plugins: anyio-3.6.2
collected 1 item

tests/test_tasks.py .                                                        [100%]

================================ 1 passed in 0.20s =================================

在继续之前快速浏览一下项目结构:

├── .gitignore
├── LICENSE
├── README.md
├── docker-compose.yml
└── project
    ├── Dockerfile
    ├── main.py
    ├── requirements.txt
    ├── static
    │   ├── main.css
    │   └── main.js
    ├── templates
    │   ├── _base.html
    │   ├── footer.html
    │   └── home.html
    └── tests
        ├── __init__.py
        ├── conftest.py
        └── test_tasks.py

触发任务

project/templates/home.htmlonclick中的事件处理程序设置为监听按钮点击:

<div class="btn-group" role="group" aria-label="Basic example">
  <button type="button" class="btn btn-primary" onclick="handleClick(1)">Short</a>
  <button type="button" class="btn btn-primary" onclick="handleClick(2)">Medium</a>
  <button type="button" class="btn btn-primary" onclick="handleClick(3)">Long</a>
</div>

onclick在project/static/main.jshandleClick中找到的调用,它使用适当的任务类型向服务器发送 AJAX POST 请求:、或。123

function handleClick(type) {
  fetch('/tasks', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ type: type }),
  })
  .then(response => response.json())
  .then(res => getStatus(res.data.task_id));
}

在服务器端,已经配置了一个路由来处理project/main.py中的请求:

@app.post("/tasks", status_code=201)
def run_task(payload = Body(...)):
    task_type = payload["type"]
    return JSONResponse(task_type)

现在到了有趣的部分——连接 Celery!

芹菜设置

首先将 Celery 和 Redis 添加到requirements.txt文件中:

aiofiles==23.1.0
celery==5.2.7
fastapi==0.95.0
Jinja2==3.1.2
pytest==7.2.2
redis==4.5.4
requests==2.28.2
uvicorn==0.21.1
httpx==0.23.3

Celery 使用消息代理——RabbitMQ 、RedisAWS 简单队列服务 (SQS) ——来促进 Celery worker 和 Web 应用程序之间的通信消息被添加到代理,然后由工作人员处理。完成后,结果将添加到后端。

Redis 将同时用作代理和后端。将 Redis 和 Celery worker添加到docker-compose.yml文件中,如下所示:

version: '3.8'

services:

  web:
    build: ./project
    ports:
      - 8004:8000
    command: uvicorn main:app --host 0.0.0.0 --reload
    volumes:
      - ./project:/usr/src/app
    environment:
      - CELERY_BROKER_URL=redis://redis:6379/0
      - CELERY_RESULT_BACKEND=redis://redis:6379/0
    depends_on:
      - redis

  worker:
    build: ./project
    command: celery -A worker.celery worker --loglevel=info
    volumes:
      - ./project:/usr/src/app
    environment:
      - CELERY_BROKER_URL=redis://redis:6379/0
      - CELERY_RESULT_BACKEND=redis://redis:6379/0
    depends_on:
      - web
      - redis

  redis:
    image: redis:7

注意celery -A worker.celery worker --loglevel=info

  1. celery worker用于启动 Celery worker
  2. -A worker.celery运行 Celery应用程序(我们将在稍后定义)
  3. --loglevel=info将日志记录级别设置为信息

接下来,在“项目”中创建一个名为worker.py的新文件:

import os
import time

from celery import Celery


celery = Celery(__name__)
celery.conf.broker_url = os.environ.get("CELERY_BROKER_URL", "redis://localhost:6379")
celery.conf.result_backend = os.environ.get("CELERY_RESULT_BACKEND", "redis://localhost:6379")


@celery.task(name="create_task")
def create_task(task_type):
    time.sleep(int(task_type) * 10)
    return True

在这里,我们创建了一个新的 Celery 实例,并使用任务装饰器定义了一个新的 Celery 任务函数,名为create_task.

请记住,任务本身将由 Celery worker 执行。

触发任务

更新main.py中的路由处理程序以启动任务并使用任务 ID 进行响应:

@app.post("/tasks", status_code=201)
def run_task(payload = Body(...)):
    task_type = payload["type"]
    task = create_task.delay(int(task_type))
    return JSONResponse({"task_id": task.id})

不要忘记导入任务:

from worker import create_task

构建图像并启动新容器:

$ docker-compose up -d --build

要触发新任务,请运行:

$ curl http://localhost:8004/tasks -H "Content-Type: application/json" --data '{"type": 0}'

你应该看到类似的东西:

{
  "task_id": "14049663-6257-4a1f-81e5-563c714e90af"
}

任务状态

回到handleClick客户端的功能:

function handleClick(type) {
  fetch('/tasks', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ type: type }),
  })
  .then(response => response.json())
  .then(res => getStatus(res.data.task_id));
}

当响应从原始 AJAX 请求返回时,我们继续getStatus()每秒调用任务 ID:

function getStatus(taskID) {
  fetch(`/tasks/${taskID}`, {
    method: 'GET',
    headers: {
      'Content-Type': 'application/json'
    },
  })
  .then(response => response.json())
  .then(res => {
    const html = `
      <tr>
        <td>${taskID}</td>
        <td>${res.data.task_status}</td>
        <td>${res.data.task_result}</td>
      </tr>`;
    document.getElementById('tasks').prepend(html);
    const newRow = document.getElementById('table').insertRow();
    newRow.innerHTML = html;
    const taskStatus = res.data.task_status;
    if (taskStatus === 'finished' || taskStatus === 'failed') return false;
    setTimeout(function() {
      getStatus(res.data.task_id);
    }, 1000);
  })
  .catch(err => console.log(err));
}

如果响应成功,一个新行将添加到 DOM 上的表中。

更新get_status路由处理程序以返回状态:

@app.get("/tasks/{task_id}")
def get_status(task_id):
    task_result = AsyncResult(task_id)
    result = {
        "task_id": task_id,
        "task_status": task_result.status,
        "task_result": task_result.result
    }
    return JSONResponse(result)

导入异步结果

from celery.result import AsyncResult

更新容器:

$ docker-compose up -d --build

触发新任务:

$ curl http://localhost:8004/tasks -H "Content-Type: application/json" --data '{"type": 1}'

然后,从响应中获取task_id并调用更新的端点以查看状态:

$ curl http://localhost:8004/tasks/f3ae36f1-58b8-4c2b-bf5b-739c80e9d7ff

{
  "task_id": "455234e0-f0ea-4a39-bbe9-e3947e248503",
  "task_result": true,
  "task_status": "SUCCESS"
}

同样在浏览器中测试一下:

fastapi,芹菜,码头工人

芹菜原木

在docker-compose.yml中更新worker服务,以便将 Celery 日志转储到日志文件中:

worker:
  build: ./project
  command: celery -A worker.celery worker --loglevel=info --logfile=logs/celery.log
  volumes:
    - ./project:/usr/src/app
  environment:
    - CELERY_BROKER_URL=redis://redis:6379/0
    - CELERY_RESULT_BACKEND=redis://redis:6379/0
  depends_on:
    - web
    - redis

在“project”中添加一个名为“logs”的新目录。然后,将一个名为celery.log的新文件添加到新创建的目录中。

更新:

$ docker-compose up -d --build

由于我们设置了卷,您应该会看到日志文件在本地填满:

[2023-04-05 16:10:33,257: INFO/MainProcess] Connected to redis://redis:6379/0
[2023-04-05 16:10:33,262: INFO/MainProcess] mingle: searching for neighbors
[2023-04-05 16:10:34,271: INFO/MainProcess] mingle: all alone
[2023-04-05 16:10:34,283: INFO/MainProcess] celery@6ea5007507db ready.
[2023-04-05 16:11:49,400: INFO/MainProcess]
  Task create_task[7f0022ec-bcc8-4eff-b825-bde60d15f824] received
[2023-04-05 16:11:59,418: INFO/ForkPoolWorker-7]
  Task create_task[7f0022ec-bcc8-4eff-b825-bde60d15f824]
  succeeded in 10.015363933052868s: True

花卉仪表盘

Flower是一个轻量级的、实时的、基于 Web 的 Celery 监控工具。您可以监控当前正在运行的任务、增加或减少工作池、查看图表和大量统计数据等等。

将其添加到requirements.txt

aiofiles==23.1.0
celery==5.2.7
fastapi==0.95.0
flower==1.2.0
Jinja2==3.1.2
pytest==7.2.2
redis==4.5.4
requests==2.28.2
uvicorn==0.21.1
httpx==0.23.3

然后,向docker-compose.yml添加一个新服务:

dashboard:
  build: ./project
  command: celery --broker=redis://redis:6379/0 flower --port=5555
  ports:
    - 5556:5555
  environment:
    - CELERY_BROKER_URL=redis://redis:6379/0
    - CELERY_RESULT_BACKEND=redis://redis:6379/0
  depends_on:
    - web
    - redis
    - worker

测试一下:

$ docker-compose up -d --build

导航到http://localhost:5556以查看仪表板。你应该看到一名工人准备好了:

花仪表板

启动更多任务以全面测试仪表板:

花仪表板

尝试添加更多的 worker 以查看这对事情有何影响:

$ docker-compose up -d --build --scale worker=3

测试

让我们从最基本的测试开始:

def test_task():
    assert create_task.run(1)
    assert create_task.run(2)
    assert create_task.run(3)

将上面的测试用例添加到project/tests/test_tasks.py,然后添加以下导入:

from worker import create_task

单独运行该测试:

$ docker-compose exec web python -m pytest -k "test_task and not test_home"

运行大约需要一分钟:

=============================== test session starts ================================
platform linux -- Python 3.11.2, pytest-7.2.2, pluggy-1.0.0
rootdir: /usr/src/app, configfile: pytest.ini
plugins: anyio-3.6.2
collected 2 items / 1 deselected / 1 selected

tests/test_tasks.py .                                                        [100%]

==================== 1 passed, 1 deselected in 60.07s (0:01:00) ====================

值得注意的是,在上面的断言中,我们使用方法.run(而不是.delay)在没有 Celery worker 的情况下直接运行任务。

想模拟.run加快速度的方法吗?

@patch("worker.create_task.run")
def test_mock_task(mock_run):
    assert create_task.run(1)
    create_task.run.assert_called_once_with(1)

    assert create_task.run(2)
    assert create_task.run.call_count == 2

    assert create_task.run(3)
    assert create_task.run.call_count == 3

进口:

from unittest.mock import patch

测试:

$ docker-compose exec web python -m pytest -k "test_mock_task"

=============================== test session starts ================================
platform linux -- Python 3.11.2, pytest-7.2.2, pluggy-1.0.0
rootdir: /usr/src/app, configfile: pytest.ini
plugins: anyio-3.6.2
collected 2 items / 1 deselected / 1 selected

tests/test_tasks.py .                                                        [100%]

========================= 1 passed, 1 deselected in 0.10s ==========================

快多了!

完整的集成测试怎么样?

def test_task_status(test_app):
    response = test_app.post(
        "/tasks",
        data=json.dumps({"type": 1})
    )
    content = response.json()
    task_id = content["task_id"]
    assert task_id

    response = test_app.get(f"tasks/{task_id}")
    content = response.json()
    assert content == {"task_id": task_id, "task_status": "PENDING", "task_result": None}
    assert response.status_code == 200

    while content["task_status"] == "PENDING":
        response = test_app.get(f"tasks/{task_id}")
        content = response.json()
    assert content == {"task_id": task_id, "task_status": "SUCCESS", "task_result": True}

请记住,此测试使用开发中使用的相同代理和后端。您可能想要实例化一个新的 Celery 应用程序进行测试。

添加导入:

import json

确保测试通过。

结论

这是关于如何配置 Celery 以在 FastAPI 应用程序中运行长时间运行任务的基本指南。您应该让队列处理任何可能阻塞或减慢面向用户代码的进程。

Celery 还可用于执行可重复的任务并分解复杂的资源密集型任务,以便计算工作量可以分布在多台机器上,以减少 (1) 完成时间和 (2) 机器处理负载客户要求。

最后,如果您对如何使用 WebSockets 检查 Celery 任务的状态而不是使用 AJAX 轮询感到好奇,请查看Celery 和 FastAPI 权威指南课程。

从repo中获取代码。

文章原文出处:https: //testdriven.io/

#fastapi #celery #tasks 

如何使用 FastAPI 和 Celery 执行异步任务
Rocio  O'Keefe

Rocio O'Keefe

1680847260

How to Asynchronous Tasks with FastAPI and Celery

If a long-running process is part of your application's workflow, rather than blocking the response, you should handle it in the background, outside the normal request/response flow.

Perhaps your web application requires users to submit a thumbnail (which will probably need to be re-sized) and confirm their email when they register. If your application processed the image and sent a confirmation email directly in the request handler, then the end user would have to wait unnecessarily for them both to finish processing before the page loads or updates. Instead, you'll want to pass these processes off to a task queue and let a separate worker process deal with it, so you can immediately send a response back to the client. The end user can then do other things on the client-side while the processing takes place. Your application is also free to respond to requests from other users and clients.

To achieve this, we'll walk you through the process of setting up and configuring Celery and Redis for handling long-running processes in a FastAPI app. We'll also use Docker and Docker Compose to tie everything together. Finally, we'll look at how to test the Celery tasks with unit and integration tests.

Objectives

By the end of this tutorial, you will be able to:

  1. Integrate Celery into a FastAPI app and create tasks.
  2. Containerize FastAPI, Celery, and Redis with Docker.
  3. Run processes in the background with a separate worker process.
  4. Save Celery logs to a file.
  5. Set up Flower to monitor and administer Celery jobs and workers.
  6. Test a Celery task with both unit and integration tests.

Background Tasks

Again, to improve user experience, long-running processes should be run outside the normal HTTP request/response flow, in a background process.

Examples:

  1. Running machine learning models
  2. Sending confirmation emails
  3. Web scraping and crawling
  4. Analyzing data
  5. Processing images
  6. Generating reports

As you're building out an app, try to distinguish tasks that should run during the request/response lifecycle, like CRUD operations, from those that should run in the background.

It's worth noting that you can leverage FastAPI's BackgroundTasks class, which comes directly from Starlette, to run tasks in the background.

For example:

from fastapi import BackgroundTasks


def send_email(email, message):
    pass


@app.get("/")
async def ping(background_tasks: BackgroundTasks):
    background_tasks.add_task(send_email, "email@address.com", "Hi!")
    return {"message": "pong!"}

So, when should you use Celery instead of BackgroundTasks?

  1. CPU intensive tasks: Celery should be used for tasks that perform heavy background computations since BackgroundTasks runs in the same event loop that serves your app's requests.
  2. Task queue: If you require a task queue to manage the tasks and workers, you should use Celery. Often you'll want to retrieve the status of a job and then perform some action based on the status -- e.g., send an error email, kick off a different background task, or retry the task. Celery manages all this for you.

Workflow

Our goal is to develop a FastAPI application that works in conjunction with Celery to handle long-running processes outside the normal request/response cycle.

  1. The end user kicks off a new task via a POST request to the server-side.
  2. Within the route handler, a task is added to the queue and the task ID is sent back to the client-side.
  3. Using AJAX, the client continues to poll the server to check the status of the task while the task itself is running in the background.

fastapi and celery queue user flow

Project Setup

Clone down the base project from the fastapi-celery repo, and then check out the v1 tag to the master branch:

$ git clone https://github.com/testdrivenio/fastapi-celery --branch v1 --single-branch
$ cd fastapi-celery
$ git checkout v1 -b master

Since we'll need to manage three processes in total (FastAPI, Redis, Celery worker), we'll use Docker to simplify our workflow by wiring them up so that they can all be run from one terminal window with a single command.

From the project root, create the images and spin up the Docker containers:

$ docker-compose up -d --build

Once the build is complete, navigate to http://localhost:8004:

fastapi project

Make sure the tests pass as well:

$ docker-compose exec web python -m pytest

=============================== test session starts ================================
platform linux -- Python 3.11.2, pytest-7.2.2, pluggy-1.0.0
rootdir: /usr/src/app
plugins: anyio-3.6.2
collected 1 item

tests/test_tasks.py .                                                        [100%]

================================ 1 passed in 0.20s =================================

Take a quick look at the project structure before moving on:

├── .gitignore
├── LICENSE
├── README.md
├── docker-compose.yml
└── project
    ├── Dockerfile
    ├── main.py
    ├── requirements.txt
    ├── static
    │   ├── main.css
    │   └── main.js
    ├── templates
    │   ├── _base.html
    │   ├── footer.html
    │   └── home.html
    └── tests
        ├── __init__.py
        ├── conftest.py
        └── test_tasks.py

Trigger a Task

An onclick event handler in project/templates/home.html is set up that listens for a button click:

<div class="btn-group" role="group" aria-label="Basic example">
  <button type="button" class="btn btn-primary" onclick="handleClick(1)">Short</a>
  <button type="button" class="btn btn-primary" onclick="handleClick(2)">Medium</a>
  <button type="button" class="btn btn-primary" onclick="handleClick(3)">Long</a>
</div>

onclick calls handleClick found in project/static/main.js, which sends an AJAX POST request to the server with the appropriate task type: 1, 2, or 3.

function handleClick(type) {
  fetch('/tasks', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ type: type }),
  })
  .then(response => response.json())
  .then(res => getStatus(res.data.task_id));
}

On the server-side, a route is already configured to handle the request in project/main.py:

@app.post("/tasks", status_code=201)
def run_task(payload = Body(...)):
    task_type = payload["type"]
    return JSONResponse(task_type)

Now comes the fun part -- wiring up Celery!

Celery Setup

Start by adding both Celery and Redis to the requirements.txt file:

aiofiles==23.1.0
celery==5.2.7
fastapi==0.95.0
Jinja2==3.1.2
pytest==7.2.2
redis==4.5.4
requests==2.28.2
uvicorn==0.21.1
httpx==0.23.3

Celery uses a message broker -- RabbitMQ, Redis, or AWS Simple Queue Service (SQS) -- to facilitate communication between the Celery worker and the web application. Messages are added to the broker, which are then processed by the worker(s). Once done, the results are added to the backend.

Redis will be used as both the broker and backend. Add both Redis and a Celery worker to the docker-compose.yml file like so:

version: '3.8'

services:

  web:
    build: ./project
    ports:
      - 8004:8000
    command: uvicorn main:app --host 0.0.0.0 --reload
    volumes:
      - ./project:/usr/src/app
    environment:
      - CELERY_BROKER_URL=redis://redis:6379/0
      - CELERY_RESULT_BACKEND=redis://redis:6379/0
    depends_on:
      - redis

  worker:
    build: ./project
    command: celery -A worker.celery worker --loglevel=info
    volumes:
      - ./project:/usr/src/app
    environment:
      - CELERY_BROKER_URL=redis://redis:6379/0
      - CELERY_RESULT_BACKEND=redis://redis:6379/0
    depends_on:
      - web
      - redis

  redis:
    image: redis:7

Take note of celery -A worker.celery worker --loglevel=info:

  1. celery worker is used to start a Celery worker
  2. -A worker.celery runs the Celery Application (which we'll define shortly)
  3. --loglevel=info sets the logging level to info

Next, create a new file called worker.py in "project":

import os
import time

from celery import Celery


celery = Celery(__name__)
celery.conf.broker_url = os.environ.get("CELERY_BROKER_URL", "redis://localhost:6379")
celery.conf.result_backend = os.environ.get("CELERY_RESULT_BACKEND", "redis://localhost:6379")


@celery.task(name="create_task")
def create_task(task_type):
    time.sleep(int(task_type) * 10)
    return True

Here, we created a new Celery instance, and using the task decorator, we defined a new Celery task function called create_task.

Keep in mind that the task itself will be executed by the Celery worker.

Trigger a Task

Update the route handler in main.py to kick off the task and respond with the task ID:

@app.post("/tasks", status_code=201)
def run_task(payload = Body(...)):
    task_type = payload["type"]
    task = create_task.delay(int(task_type))
    return JSONResponse({"task_id": task.id})

Don't forget to import the task:

from worker import create_task

Build the images and spin up the new containers:

$ docker-compose up -d --build

To trigger a new task, run:

$ curl http://localhost:8004/tasks -H "Content-Type: application/json" --data '{"type": 0}'

You should see something like:

{
  "task_id": "14049663-6257-4a1f-81e5-563c714e90af"
}

Task Status

Turn back to the handleClick function on the client-side:

function handleClick(type) {
  fetch('/tasks', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ type: type }),
  })
  .then(response => response.json())
  .then(res => getStatus(res.data.task_id));
}

When the response comes back from the original AJAX request, we then continue to call getStatus() with the task ID every second:

function getStatus(taskID) {
  fetch(`/tasks/${taskID}`, {
    method: 'GET',
    headers: {
      'Content-Type': 'application/json'
    },
  })
  .then(response => response.json())
  .then(res => {
    const html = `
      <tr>
        <td>${taskID}</td>
        <td>${res.data.task_status}</td>
        <td>${res.data.task_result}</td>
      </tr>`;
    document.getElementById('tasks').prepend(html);
    const newRow = document.getElementById('table').insertRow();
    newRow.innerHTML = html;
    const taskStatus = res.data.task_status;
    if (taskStatus === 'finished' || taskStatus === 'failed') return false;
    setTimeout(function() {
      getStatus(res.data.task_id);
    }, 1000);
  })
  .catch(err => console.log(err));
}

If the response is successful, a new row is added to the table on the DOM.

Update the get_status route handler to return the status:

@app.get("/tasks/{task_id}")
def get_status(task_id):
    task_result = AsyncResult(task_id)
    result = {
        "task_id": task_id,
        "task_status": task_result.status,
        "task_result": task_result.result
    }
    return JSONResponse(result)

Import AsyncResult:

from celery.result import AsyncResult

Update the containers:

$ docker-compose up -d --build

Trigger a new task:

$ curl http://localhost:8004/tasks -H "Content-Type: application/json" --data '{"type": 1}'

Then, grab the task_id from the response and call the updated endpoint to view the status:

$ curl http://localhost:8004/tasks/f3ae36f1-58b8-4c2b-bf5b-739c80e9d7ff

{
  "task_id": "455234e0-f0ea-4a39-bbe9-e3947e248503",
  "task_result": true,
  "task_status": "SUCCESS"
}

Test it out in the browser as well:

fastapi, celery, docker

Celery Logs

Update the worker service, in docker-compose.yml, so that Celery logs are dumped to a log file:

worker:
  build: ./project
  command: celery -A worker.celery worker --loglevel=info --logfile=logs/celery.log
  volumes:
    - ./project:/usr/src/app
  environment:
    - CELERY_BROKER_URL=redis://redis:6379/0
    - CELERY_RESULT_BACKEND=redis://redis:6379/0
  depends_on:
    - web
    - redis

Add a new directory to "project" called "logs. Then, add a new file called celery.log to that newly created directory.

Update:

$ docker-compose up -d --build

You should see the log file fill up locally since we set up a volume:

[2023-04-05 16:10:33,257: INFO/MainProcess] Connected to redis://redis:6379/0
[2023-04-05 16:10:33,262: INFO/MainProcess] mingle: searching for neighbors
[2023-04-05 16:10:34,271: INFO/MainProcess] mingle: all alone
[2023-04-05 16:10:34,283: INFO/MainProcess] celery@6ea5007507db ready.
[2023-04-05 16:11:49,400: INFO/MainProcess]
  Task create_task[7f0022ec-bcc8-4eff-b825-bde60d15f824] received
[2023-04-05 16:11:59,418: INFO/ForkPoolWorker-7]
  Task create_task[7f0022ec-bcc8-4eff-b825-bde60d15f824]
  succeeded in 10.015363933052868s: True

Flower Dashboard

Flower is a lightweight, real-time, web-based monitoring tool for Celery. You can monitor currently running tasks, increase or decrease the worker pool, view graphs and a number of statistics, to name a few.

Add it to requirements.txt:

aiofiles==23.1.0
celery==5.2.7
fastapi==0.95.0
flower==1.2.0
Jinja2==3.1.2
pytest==7.2.2
redis==4.5.4
requests==2.28.2
uvicorn==0.21.1
httpx==0.23.3

Then, add a new service to docker-compose.yml:

dashboard:
  build: ./project
  command: celery --broker=redis://redis:6379/0 flower --port=5555
  ports:
    - 5556:5555
  environment:
    - CELERY_BROKER_URL=redis://redis:6379/0
    - CELERY_RESULT_BACKEND=redis://redis:6379/0
  depends_on:
    - web
    - redis
    - worker

Test it out:

$ docker-compose up -d --build

Navigate to http://localhost:5556 to view the dashboard. You should see one worker ready to go:

flower dashboard

Kick off a few more tasks to fully test the dashboard:

flower dashboard

Try adding a few more workers to see how that affects things:

$ docker-compose up -d --build --scale worker=3

Tests

Let's start with the most basic test:

def test_task():
    assert create_task.run(1)
    assert create_task.run(2)
    assert create_task.run(3)

Add the above test case to project/tests/test_tasks.py, and then add the following import:

from worker import create_task

Run that test individually:

$ docker-compose exec web python -m pytest -k "test_task and not test_home"

It should take about one minute to run:

=============================== test session starts ================================
platform linux -- Python 3.11.2, pytest-7.2.2, pluggy-1.0.0
rootdir: /usr/src/app, configfile: pytest.ini
plugins: anyio-3.6.2
collected 2 items / 1 deselected / 1 selected

tests/test_tasks.py .                                                        [100%]

==================== 1 passed, 1 deselected in 60.07s (0:01:00) ====================

It's worth noting that in the above asserts, we used the .run method (rather than .delay) to run the task directly without a Celery worker.

Want to mock the .run method to speed things up?

@patch("worker.create_task.run")
def test_mock_task(mock_run):
    assert create_task.run(1)
    create_task.run.assert_called_once_with(1)

    assert create_task.run(2)
    assert create_task.run.call_count == 2

    assert create_task.run(3)
    assert create_task.run.call_count == 3

Import:

from unittest.mock import patch

Test:

$ docker-compose exec web python -m pytest -k "test_mock_task"

=============================== test session starts ================================
platform linux -- Python 3.11.2, pytest-7.2.2, pluggy-1.0.0
rootdir: /usr/src/app, configfile: pytest.ini
plugins: anyio-3.6.2
collected 2 items / 1 deselected / 1 selected

tests/test_tasks.py .                                                        [100%]

========================= 1 passed, 1 deselected in 0.10s ==========================

Much quicker!

How about a full integration test?

def test_task_status(test_app):
    response = test_app.post(
        "/tasks",
        data=json.dumps({"type": 1})
    )
    content = response.json()
    task_id = content["task_id"]
    assert task_id

    response = test_app.get(f"tasks/{task_id}")
    content = response.json()
    assert content == {"task_id": task_id, "task_status": "PENDING", "task_result": None}
    assert response.status_code == 200

    while content["task_status"] == "PENDING":
        response = test_app.get(f"tasks/{task_id}")
        content = response.json()
    assert content == {"task_id": task_id, "task_status": "SUCCESS", "task_result": True}

Keep in mind that this test uses the same broker and backend used in development. You may want to instantiate a new Celery app for testing.

Add the import:

import json

Ensure the test passes.

Conclusion

This has been a basic guide on how to configure Celery to run long-running tasks in a FastAPI app. You should let the queue handle any processes that could block or slow down the user-facing code.

Celery can also be used to execute repeatable tasks and break up complex, resource-intensive tasks so that the computational workload can be distributed across a number of machines to reduce (1) the time to completion and (2) the load on the machine handling client requests.

Finally, if you're curious about how to use WebSockets to check the status of a Celery task, instead of using AJAX polling, check out the The Definitive Guide to Celery and FastAPI course.

Grab the code from the repo.

Original article source at: https://testdriven.io/

#fastapi #celery #tasks 

How to Asynchronous Tasks with FastAPI and Celery
戈 惠鈺

戈 惠鈺

1680816720

在 Python 中使用 FastAPI 的介绍

在本 FastAPI 教程中,我们将了解 FastAPI 教程:在 Python 中使用 FastAPI 的介绍。API(应用程序编程接口)是现代架构的支柱,因为它们允许应用程序模块化和解耦。这意味着您可以快速轻松地构建应用程序,让您轻松维护和更新它们。 

API 在机器学习中也非常重要,因为它们允许不同的应用程序共享数据并协同工作,从而节省时间和精力。在 Python 中构建 API 有许多不同的框架。在 Python 中创建 API 的一些最流行的框架是 Django、Flask 和 FastAPI。本教程深入探讨了称为 FastAPI 的框架之一。

什么是 API?

API代表应用程序编程接口。API 是一种软件中介,它允许两个应用程序相互通信。当您在手机上使用某个应用程序时,该应用程序会连接到 Internet 并将数据发送到服务器。然后服务器处理数据并将其发送回您的手机。然后,您手机上的应用程序会解释数据并以可读的方式呈现给您。 

API 就像餐厅里的服务员。服务员接受您的订单并将其发送到厨房。然后厨房准备食物并将其送回给服务员。然后服务员把食物端给你。 

以同样的方式,API 从应用程序接收请求并将其发送到服务器。然后服务器处理请求并将数据发送回应用程序。然后应用程序解释数据并将其呈现给用户。

一个简单的API架构设计

图片来源:https://www.techfunnel.com/wp-content/uploads/2021/07/api.png

如果您想了解有关机器学习管道、API 和 MLOps 的更多信息,可以查看我们的机器学习、管道、部署和 MLOps 教程

什么是 FastAPI

FastAPI是一个高性能的 Web 框架,用于基于标准 Python 类型提示使用 Python 3.7+ 构建 API。它可以帮助开发人员快速高效地构建应用程序。FastAPI 建立在 Starlette 网络服务器之上,包括使构建网络应用程序更容易的功能,例如自动数据验证、错误处理和交互式 API 文档。 

我们将在本节中单独查看所有这些功能。首先,让我们看看 FastAPI 原始文档中指出的关键特性。

  • 性能:与 NodeJS 和 Go 语言相当。
  • 速度:将开发速度提高 2-3 倍。
  • 简单:强大的编辑器支持。处处圆满。易于学习和使用。
  • 健壮:具有自动交互式文档的生产就绪代码。
  • 基于 OpenAPI:与 OpenAPI 和 JSON Schema 完全兼容。

安装 FastAPI

FastAPI 需要 Python 3.7+。它可以使用 pip 安装。您将需要安装 FastAPI 和 ASGI 服务器 `uvicorn`。

``

# install fastapi

pip install fastapi




# install uvicorn
pip install uvicorn

``

创建一个简单的 API

让我们直接开始创建一个非常简单的玩具 API。我正在使用 VS Code 来实现它,但您可以使用任何您喜欢的编辑器。

```

from typing import Union

from fastapi import FastAPI




app = FastAPI()




@app.get("")

def read_root():

    return {"Hello": "World"}




@app.get("/items/{item_id}")

def read_item(item_id: int, q: Union[str, None] = None):

    return {"item_id": item_id, "q": q}

```

(从原始文档复制的示例)。感谢@tiangolo。

现在使用命令行终端,使用以下命令运行此 API:

```

uvicorn main:app –reload

```

`main` 是 Python 文件的名称,`app` 是存储 FastAPI 类的变量。您可以随意命名它们。一旦你运行上面的命令,你会在你的终端上看到类似这样的东西:

命令终端

转到浏览器中的链接,如果您看到显示“Hello World”的页面,则 API 已启动并正在运行。

在浏览器的本地主机上运行的 API

图片作者

祝贺您构建了您的第一个 API。 

交互式 API 文档

FastAPI 使用用于定义 API 的OpenAPI标准为您的所有 API 生成一个“模式” 。“模式”是对某物的定义或描述。不是实现它的代码,而只是一个抽象的描述。OpenAPI 架构为 FastAPI 中包含的两个交互式文档系统提供支持。

要查看文档,只需将 `/docs` 添加到 url (` http://127.0.0.1:8000/docs `)。此链接将显示自动交互式 API 文档。

FastAPI 创建的自动化文档

图片作者

单击右上角的“试用”按钮以测试 API。

FastAPI 2 创建的自动化文档

图片作者

你可以看到响应主体是一个字典。这是 `main.py` 中定义的 `read_item` 函数的返回调用。您还可以看到请求 url `http://127.0.0.1:8000/items/1?q=orange`。`1` 和 `orange` 是我们对 API 的输入。

FastAPI 中提供了一个替代的交互式自动文档。要检查这一点,请转到 http://127.0.0.1:8000/redoc。这是它的样子:

由 FastAPI 3 创建的自动化文档

图片作者

更高级的例子

在构建 API 时,“路径”定义了请求的路由或端点。不过,这里我们还要多做一个选择,那就是“运营”。这里的“操作”一词指的是 HTTP“方法”之一。通过使用这些所谓的“方法”中的一种(或多种),您可以与 HTTP 协议支持的几种路径中的每一种进行通信。通常,您会使用:

  • POST:创建数据。
  • GET:读取数据。
  • PUT:更新数据。
  • 删除:删除数据。
  • 以及其他一些高级的 

FastAPI 支持所有的 http 方法。 

FastAPI 基于 Python 类型提示构建的事实是该框架的另一个关键方面。Python 3.6 及更高版本支持类型提示。类型提示是一种特殊的语法,可以声明变量的类型。 

为您的变量声明类型使编辑器和其他工具能够为您提供更好的帮助。让我们看一个高级示例。

我们将修改我们的 `main.py` 文件以包含一个新的 `PUT` 请求,该请求将采用不同数据类型的多个输入。 

```

from typing import Union




from fastapi import FastAPI

from pydantic import BaseModel




app = FastAPI()




class Item(BaseModel):

    name: str

    price: float

    is_offer: Union[bool, None] = None




@app.get("")

def read_root():

    return {"Hello": "World"}




@app.get("/items/{item_id}")

def read_item(item_id: int, q: Union[str, None] = None):

    return {"item_id": item_id, "q": q}




@app.put("/items/{item_id}")

def update_item(item_id: int, item: Item):

    return {"item_name": item.name, "item_id": item_id}

```

(从原始文档复制的示例)。感谢@tiangolo。

改变:

添加了一个接受两个输入的“put”请求。`item_id` 是一个整数,`item` 类型指向创建的自定义类`Item`,并从`pydantic` 继承`BaseModel`。`Item` 类包含三个属性:`name`、`price`、`is_offer`,它们都有不同的数据类型。

FastAPI 将检查: 

  • `name` 是一个 `str`。
  • `price` 是一个 `float`。
  • `is_offer` 是一个布尔值,如果存在的话。

使用类型提示的好处是您可以使用标准 Python (3.6+) 将参数类型、主体等声明为函数参数。你会得到:

  • 编辑器支持,包括自动完成、类型检查
  • 数据验证
  • 输入数据的转换
  • 输出数据的转换
  • 容易理解的错误。

FastAPI 与 Django 和 Flask 的比较

所有这三个框架都是 Python Web 框架,您可以使用它们来开发 Web 应用程序。他们每个人都有自己的长处和短处。

Django 是一个功能齐全的框架,包含您入门所需的一切,包括内置 ORM 和管理面板。对于初学者来说可能有点不知所措,但其全面的文档使其易于学习。

Flask 是一个轻量级且易于上手的微框架。它不像 Django 包含那么多功能,但它非常适合简单的项目。

FastAPI 是一个新的框架,旨在快速且易于使用。它包括自动数据验证和文档等功能。 

 姜戈烧瓶快速API
社区

大的。 

66K GitHub 星数

大的。 

61K GitHub 星数

大的。 

50K GitHub 星数

表现Django 很大。就性能而言,它不是最好的。Flask 是一个微型网络框架。它的性能优于 Django。FastAPI 是最快的 Web 框架之一,具有本机异步支持,可提高框架的效率。 
异步支持是的,延迟时间有限。

不。 

需要异步

FastAPI 提供本机异步支持。
使用方便Django 非常庞大,因此学习起来有点复杂。Flask 易于学习且使用起来非常简单。FastAPI 是三者中最简单的。
交互式文档不互动是(OpenAI、Redoc)
数据验证是的


FastAPI 性能基准

根据techempower运行的测试结果,FastAPI 在整体性能方面优于所有其他框架。 

API 性能基准

资料来源:https://www.techempower.com/benchmarks/

示例:使用 PyCaret 构建端到端机器学习管道并使用 FastAPI 进行部署 

在本节中,我们将快速构建机器学习管道,然后创建 API 来为模型提供服务。我们将使用低代码 Python 库PyCaret来构建管道并创建 API。PyCaret 与 FastAPI 集成,这使得创建和提供机器学习模型作为 API 变得极其容易。

PyCaret

PyCaret 是 Python 中的开源低代码机器学习库,可自动执行机器学习工作流程。它是一种端到端的机器学习和模型管理工具,可以成倍地加快实验周期并提高您的工作效率。

```

pip install pycaret

```




```

import pycaret

pycaret.__version__

>>> 2.3.10

```

在此示例中,我们将使用“保险”数据集。这是一个回归用例,用于根据年龄、性别、BMI 和地区预测医疗费用。 

```

from pycaret.datasets import get_data

data = get_data(‘insurance’)

```

示例数据集

图片作者

接下来我们将从 pycaret 初始化 `setup` 函数。此函数在 PyCaret 中初始化实验,并根据函数中传递的所有参数创建转换管道。 

`setup` 必须在任何其他函数之前首先执行。它需要两个参数来处理“data”和“target”。`setup` 中的所有剩余参数都是可选的。`setup` 函数负责控制整个数据预处理过程。查看PyCaret 文档,全面了解 PyCaret 支持的所有预处理过程。

```

from pycaret.regression import *

s = setup(data, target = 'charges')

```

PyCaret 设置函数的输出

图片由作者输出截断。

设置完成后,我们只需一行代码即可开始模型训练和选择:`compare_models`。通过使用交叉验证,该函数训练和评估模型库中所有估计器的模型性能。此函数的结果是一个评分网格,其中包含从交叉验证获得的平均分数。
 

```

best = compare_models()

```

PyCaret 的 compare_models 函数的输出

图片作者

基于此,性能最好的模型是“Gradient Boosting Regressor”。如果需要,我们可以通过可视化分析模型,并进一步尝试通过超参数调整或模型集成来提高性能,但我们不会在本教程中这样做。 

我们将直接构建最佳模型的 API,以使用 FastAPI 在生产中提供预测服务。请记住,PyCaret 与 FastAPI 集成,因此它可以使用 `create_api` 函数从模型自动创建 REST API。

```

create_api (best, 'insurance_prediction_model')

```

API创建成功

现在要运行此 API,请打开命令提示符终端并导航到笔记本所在的文件夹,然后运行以下命令“python insurance_prediction_model.py”。 

命令行

前往“http://127.0.0.1:8000/docs”,您将看到与本教程前面部分相同的用户界面

API 位于 http:::127.0.0.1:8000:docs

图片作者

API 在 http:::127.0.0.18000:docs

图片作者

您还可以通过转到“ http://127.0.0.1:8000/redoc ”来查看替代的交互式文档

在 http:::127.0.0.1:8000:docs3 上的 API

图片作者

请记住,默认和 redoc 交互式文档均使用 OpenAPI 标准提供支持。 

如果您想查看 PyCaret 在使用 `create_api` 函数时创建的文件,您可以在与笔记本相同的文件夹中检出该文件。它看起来像这样:

```

import pandas as pd

from pycaret.regression import load_model, predict_model

from fastapi import FastAPI

import uvicorn




# Create the app

app = FastAPI()




# Load trained Pipeline

model = load_model('my_lr_api')




# Define predict function

@app.post('/predict')

def predict(age, sex, bmi, children, smoker, region):

    data = pd.DataFrame([[age, sex, bmi, children, smoker, region]])

    data.columns = ['age', 'sex', 'bmi', 'children', 'smoker', 'region']

    predictions = predict_model(model, data=data) 

    return {'prediction': list(predictions['Label'])}




if __name__ == '__main__':

    uvicorn.run(app, host='127.0.0.1', port=8000)




```

结论

本文讨论了 API 的概念以及使用它们的原因。API 在现代架构中很重要,因为它允许不同的软件程序共享数据和功能。这使得创建更可靠且更易于维护的复杂系统成为可能。

然后,我们深入研究一个相对较新的 Python 框架,称为 FastAPI。FastAPI 是一种较新的 API,旨在易于使用且高效。对于想要快速轻松地创建 API 的开发人员来说,这是一个很好的选择。

GitHub star 历史 - 使用 star-history.com 创建

GitHub star 历史 - 使用 star-history.com 创建

如果您还想学习如何使用 Flask 在 Python 中从机器学习模型创建简单的 API,

文章原文出处:https: //www.datacamp.com

#python  #fastapi 

在 Python 中使用 FastAPI 的介绍

Введение в использование FastAPI в Python

В этом учебном пособии по FastAPI мы узнаем об учебном пособии по FastAPI: введение в использование FastAPI в Python. API (интерфейс прикладного программирования) являются основой современной архитектуры, поскольку они позволяют приложениям быть модульными и независимыми. Это означает, что вы можете создавать приложения быстро и легко, что позволяет легко поддерживать и обновлять их. 

API также очень важны для машинного обучения, поскольку они позволяют различным приложениям обмениваться данными и работать вместе, экономя время и силы. Существует множество различных фреймворков для создания API в Python. Одними из самых популярных фреймворков для создания API на Python являются Django, Flask и FastAPI. Этот учебник представляет собой глубокое погружение в один из фреймворков под названием FastAPI.

Что такое API?

API означает интерфейс прикладного программирования. API — это программный посредник, который позволяет двум приложениям взаимодействовать друг с другом. Когда вы используете приложение на своем телефоне, оно подключается к Интернету и отправляет данные на сервер. Затем сервер обрабатывает данные и отправляет их обратно на ваш телефон. Затем приложение на вашем телефоне интерпретирует данные и представляет их вам в удобочитаемом виде. 

API — это как официант в ресторане. Официант принимает ваш заказ и отправляет его на кухню. Затем кухня готовит еду и отправляет ее обратно официанту. Затем официант приносит вам еду. 

Точно так же API принимает запрос от приложения и отправляет его на сервер. Затем сервер обрабатывает запрос и отправляет данные обратно в приложение. Затем приложение интерпретирует данные и представляет их пользователю.

Простой дизайн архитектуры API

Источник изображения: https://www.techfunnel.com/wp-content/uploads/2021/07/api.png

Если вы хотите узнать больше о конвейерах машинного обучения, API и MLOps, вы можете ознакомиться с нашим учебным пособием по машинному обучению, конвейерам, развертыванию и MLOps .

Что такое FastAPI

FastAPI — это высокопроизводительная веб-инфраструктура для создания API-интерфейсов с Python 3.7+ на основе стандартных подсказок типов Python. Это помогает разработчикам создавать приложения быстро и эффективно. FastAPI построен на основе веб-сервера Starlette и включает в себя функции, упрощающие создание веб-приложений, такие как автоматическая проверка данных, обработка ошибок и интерактивная документация по API. 

В этом разделе мы рассмотрим все эти функции по отдельности. Во-первых, давайте рассмотрим ключевые функции, указанные в оригинальной документации FastAPI.

  • Производительность : на уровне NodeJS и языка Go.
  • Скорость : увеличьте скорость разработки в 2-3 раза.
  • Легко : отличная поддержка редактора. Завершение везде. Простота в освоении и использовании.
  • Надежный : готовый к производству код с автоматической интерактивной документацией.
  • На основе OpenAPI : полностью совместим со схемой OpenAPI и JSON.

Установка FastAPI

FastAPI требует Python 3.7+. Его можно установить с помощью pip. Вам нужно будет установить FastAPI и ASGI-сервер uvicorn.

``

# install fastapi

pip install fastapi




# install uvicorn
pip install uvicorn

``

Создайте простой API

Давайте непосредственно приступим к созданию очень простого игрушечного API. Я использую VS Code для реализации этого, но вы можете использовать любой редактор, который вам нравится.

```

from typing import Union

from fastapi import FastAPI




app = FastAPI()




@app.get("")

def read_root():

    return {"Hello": "World"}




@app.get("/items/{item_id}")

def read_item(item_id: int, q: Union[str, None] = None):

    return {"item_id": item_id, "q": q}

```

(Пример воспроизведен из оригинальной документации ). Спасибо @tiangolo.

Теперь, используя терминал командной строки, запустите этот API с помощью следующей команды:

```

uvicorn main:app –reload

```

«main» — это имя файла Python, а «app» — это переменная, в которой хранится класс FastAPI. Вы можете назвать их как угодно. После того, как вы запустите приведенную выше команду, вы увидите что-то вроде этого на своем терминале:

Командный терминал

Перейдите по ссылке в браузере, и если вы увидите страницу с надписью «Hello World», API запущен и работает.

API работает на локальном хосте в браузере

Изображение автора

Поздравляем с созданием вашего первого API. 

Интерактивная документация по API

FastAPI создает «схему» со всеми вашими API, используя стандарт OpenAPI для определения API. «Схема» — это определение или описание чего-либо. Не тот код, который его реализует, а просто абстрактное описание. Схема OpenAPI обеспечивает работу двух систем интерактивной документации, включенных в FastAPI.

Чтобы просмотреть документацию, просто добавьте `/docs` к URL-адресу (` http://127.0.0.1:8000/docs` ). Эта ссылка покажет автоматическую интерактивную документацию по API.

Автоматизированная документация, созданная FastAPI

Изображение автора

Нажмите кнопку «Попробовать» в правом верхнем углу, чтобы протестировать API.

Автоматизированная документация, созданная FastAPI 2

Изображение автора

Вы можете видеть, что тело ответа представляет собой словарь. Это обратный вызов функции read_item, определенной в main.py. Вы также можете увидеть URL-адрес запроса `http://127.0.0.1:8000/items/1?q=orange`. «1» и «оранжевый» были нашими входными данными для API.

В FastAPI доступна альтернативная интерактивная автоматическая документация. Чтобы проверить это, перейдите по адресу http://127.0.0.1:8000/redoc`. Вот как это выглядит:

Автоматизированная документация, созданная FastAPI 3

Изображение автора

Более сложные примеры

При создании API «путь» определяет маршрут или конечную точку запроса. Однако здесь мы должны сделать еще один выбор, то есть «Операция». Слово «операция» здесь относится к одному из «методов» HTTP. Используя один (или несколько) из этих так называемых «методов», вы можете взаимодействовать с каждым из нескольких путей, поддерживаемых протоколом HTTP. Как правило, вы должны использовать:

  • POST : для создания данных.
  • ПОЛУЧИТЬ : прочитать данные.
  • PUT : обновить данные.
  • УДАЛИТЬ : удалить данные.
  • И еще несколько продвинутых 

FastAPI поддерживает все методы http. 

Тот факт, что FastAPI построен на подсказках типов Python, является еще одним ключевым аспектом этой структуры. Подсказки типов поддерживаются в версиях Python 3.6 и более поздних. Подсказки типов — это особый вид синтаксиса, который позволяет объявлять тип переменной. 

Объявление типов для ваших переменных позволяет редакторам и другим инструментам предоставлять вам улучшенную помощь. Давайте посмотрим на расширенный пример.

Мы изменим наш файл `main.py`, чтобы включить новый запрос `PUT`, который будет принимать несколько входных данных разных типов данных. 

```

from typing import Union




from fastapi import FastAPI

from pydantic import BaseModel




app = FastAPI()




class Item(BaseModel):

    name: str

    price: float

    is_offer: Union[bool, None] = None




@app.get("")

def read_root():

    return {"Hello": "World"}




@app.get("/items/{item_id}")

def read_item(item_id: int, q: Union[str, None] = None):

    return {"item_id": item_id, "q": q}




@app.put("/items/{item_id}")

def update_item(item_id: int, item: Item):

    return {"item_name": item.name, "item_id": item_id}

```

(Пример воспроизведен из оригинальной документации ). Спасибо @tiangolo.

Изменение:

Добавлен запрос `put`, который принимает два входа. `item_id` является целым числом, а тип `item` указывает на пользовательский класс `Item`, созданный и наследующий `BaseModel` от `pydantic`. Класс `Item` содержит три атрибута: `name`, `price`, `is_offer`, и все они имеют разные типы данных.

FastAPI проверит: 

  • `имя` - это `ул`.
  • `цена` является `плавающей`.
  • `is_offer` - это логическое значение, если оно присутствует.

Преимущество использования подсказок типов заключается в том, что вы один раз объявляете типы параметров, тела и т. д. как параметры функции в стандартном Python (3.6+). Ты получишь:

  • Поддержка редактора, включая автодополнение, проверку типов
  • Валидация данных
  • Преобразование входных данных
  • Преобразование выходных данных
  • Ошибки, которые легко понять.

Сравнение FastAPI с Django и Flask

Все три из этих фреймворков являются веб-фреймворками Python, которые можно использовать для разработки веб-приложений. У каждого из них есть свои сильные и слабые стороны.

Django — это полнофункциональный фреймворк, включающий в себя все необходимое для начала работы, в том числе встроенный ORM и панель администратора. Это может быть немного сложно для новичков, но его исчерпывающая документация облегчает изучение.

Flask — это легкий микрофреймворк, с которым легко начать работу. В нем не так много функций, как в Django, но он идеально подходит для простых проектов.

FastAPI — это новый фреймворк, разработанный для того, чтобы быть быстрым и простым в использовании. Он включает в себя такие функции, как автоматическая проверка данных и документация. 

 ДжангоКолбаFastAPI
Сообщество

Большой. 

66 тысяч звезд GitHub

Большой. 

61 тысяча звезд на GitHub

Большой. 

50 000 звезд на GitHub

ПроизводительностьДжанго огромен. Это не лучший вариант с точки зрения производительности.Flask — это микровеб-фреймворк. Он работает лучше, чем Django.FastAPI — один из самых быстрых веб-фреймворков со встроенной поддержкой асинхронности, которая повышает эффективность фреймворка. 
Асинхронная поддержкаДа, с ограниченной задержкой.

Нет. 

Нужен Асинкио

FastAPI обеспечивает встроенную поддержку асинхронности.
Простота использованияDjango огромен и, следовательно, немного сложен в освоении.Flask прост в освоении и довольно прост в использовании.FastAPI — самый простой из всех трех.
Интерактивная документацияНе интерактивныйНетДа (OpenAI, редок)
Проверка данныхНетНетДа


Тесты производительности FastAPI

По результатам тестов, проведенных techempower , FastAPI превосходит все остальные фреймворки по своей общей производительности. 

Тесты производительности API

Источник: https://www.techempower.com/benchmarks/

Пример: создание сквозного конвейера машинного обучения с помощью PyCaret и развертывание с помощью FastAPI 

В этом разделе мы быстро создадим конвейер машинного обучения, а затем создадим API для обслуживания модели. Мы будем использовать библиотеку Python с низким кодом PyCaret для построения конвейера и создания API. PyCaret интегрируется с FastAPI, что упрощает создание и обслуживание моделей машинного обучения в качестве API.

Пикарет

PyCaret — это библиотека машинного обучения с открытым исходным кодом на Python, которая автоматизирует рабочие процессы машинного обучения. Это комплексный инструмент машинного обучения и управления моделями, который экспоненциально ускоряет цикл экспериментов и повышает вашу продуктивность.

```

pip install pycaret

```




```

import pycaret

pycaret.__version__

>>> 2.3.10

```

В этом примере мы будем использовать набор данных «страхование». Это вариант использования регрессии для прогнозирования медицинских расходов на основе возраста, пола, ИМТ и региона. 

```

from pycaret.datasets import get_data

data = get_data(‘insurance’)

```

Образец набора данных

Изображение автора

Далее мы инициализируем функцию setup из pycaret. Эта функция инициализирует эксперимент в PyCaret и создает конвейер преобразования на основе всех параметров, переданных в функцию. 

`Настройка` должна быть выполнена перед любой другой функцией. Для работы требуется два параметра: «данные» и «цель». Все остальные аргументы в `setup` являются необязательными. Функция «настройка» отвечает за управление всеми процедурами предварительной обработки данных. Ознакомьтесь с документацией PyCaret, чтобы получить полное изложение всех процедур предварительной обработки, поддерживаемых в PyCaret.

```

from pycaret.regression import *

s = setup(data, target = 'charges')

```

Выход из функции настройки PyCaret

Изображение автора. Выходные данные усечены.

После завершения настройки мы можем начать обучение и выбор модели с помощью всего одной строки кода: `compare_models`. С помощью перекрестной проверки эта функция обучает и оценивает производительность модели всех средств оценки в библиотеке моделей. Результатом этой функции является сетка оценок, содержащая средние оценки, полученные в результате перекрестной проверки.
 

```

best = compare_models()

```

Вывод функции compare_models PyCaret

Изображение автора

Исходя из этого, наиболее эффективной моделью является «Gradient Boosting Regressor». Если мы хотим, мы можем проанализировать модель с помощью визуализации и дополнительно попытаться улучшить производительность с помощью настройки гиперпараметров или объединения моделей, но мы не будем этого делать в этом руководстве. 

Мы приступим непосредственно к созданию API лучшей модели для обслуживания прогнозов в производственной среде с использованием FastAPI. Помните, что PyCaret имеет интеграцию с FastAPI, поэтому он может автоматически создавать REST API из модели с помощью функции create_api.

```

create_api (best, 'insurance_prediction_model')

```

API успешно создан

Теперь, чтобы запустить этот API, откройте терминал командной строки, перейдите в папку, в которой находится ваш ноутбук, и выполните следующую команду `python Insurance_prediction_model.py`. 

Командная строка

Перейдите по адресу `http://127.0.0.1:8000/docs`, и вы увидите тот же пользовательский интерфейс, который вы видели ранее в этом руководстве.

API на http:::127.0.0.1:8000:docs

Изображение автора

API на http:::127.0.0.18000:docs

Изображение автора

Вы также можете просмотреть альтернативную интерактивную документацию, перейдя по адресу ` http://127.0.0.1:8000/redoc ' .

API на http:::127.0.0.1:8000:docs3

Изображение автора

Помните, что и интерактивная документация по умолчанию, и интерактивная документация в редоке основаны на стандартах OpenAPI. 

Если вы хотите увидеть файл, созданный PyCaret, когда вы использовали функцию `create_api`, вы можете извлечь файл в той же папке, что и ваш ноутбук. Это выглядит так:

```

import pandas as pd

from pycaret.regression import load_model, predict_model

from fastapi import FastAPI

import uvicorn




# Create the app

app = FastAPI()




# Load trained Pipeline

model = load_model('my_lr_api')




# Define predict function

@app.post('/predict')

def predict(age, sex, bmi, children, smoker, region):

    data = pd.DataFrame([[age, sex, bmi, children, smoker, region]])

    data.columns = ['age', 'sex', 'bmi', 'children', 'smoker', 'region']

    predictions = predict_model(model, data=data) 

    return {'prediction': list(predictions['Label'])}




if __name__ == '__main__':

    uvicorn.run(app, host='127.0.0.1', port=8000)




```

Заключение

В статье обсуждалась идея API и почему они используются. API важен в современной архитектуре, потому что он позволяет различным программам обмениваться данными и функциями. Это позволяет создавать сложные системы, более надежные и простые в обслуживании.

Затем мы углубимся в относительно новую структуру Python под названием FastAPI. FastAPI — это новый API, простой в использовании и эффективный. Это отличный вариант для разработчиков, которые хотят быстро и легко создать API.

Звездная история GitHub — создана с помощью star-history.com

Звездная история GitHub — создана с помощью star-history.com

Если вы также хотите узнать, как создать простой API из модели машинного обучения в Python с помощью Flask,

Оригинальный источник статьи: https://www.datacamp.com

#python #fastapi 

Введение в использование FastAPI в Python

Uma introdução ao uso do FastAPI em Python

Neste tutorial FastAPI, aprenderemos sobre FastAPI Tutorial: An Introduction to Using FastAPI in Python. API (Application Programming Interface) são a espinha dorsal da arquitetura moderna porque permitem que os aplicativos sejam modulares e desacoplados. Isso significa que você pode criar aplicativos construídos de forma rápida e fácil, permitindo que você os mantenha e atualize com facilidade. 

As APIs também são muito importantes no aprendizado de máquina porque permitem que diferentes aplicativos compartilhem dados e trabalhem juntos, economizando tempo e esforço. Existem muitos frameworks diferentes para construir APIs em Python. Algumas das estruturas mais populares para criar APIs em Python são Django, Flask e FastAPI. Este tutorial é um mergulho profundo em uma das estruturas chamadas FastAPI.

O que é uma API?

API significa Interface de Programação de Aplicativos. Uma API é um intermediário de software que permite que dois aplicativos conversem entre si. Quando você usa um aplicativo em seu telefone, o aplicativo se conecta à Internet e envia dados para um servidor. O servidor então processa os dados e os envia de volta para o seu telefone. O aplicativo em seu telefone interpreta os dados e os apresenta a você de forma legível. 

Uma API é como um garçom em um restaurante. O garçom anota seu pedido e o encaminha para a cozinha. A cozinha então prepara a comida e a devolve ao garçom. O garçom então traz a comida para você. 

Da mesma forma, uma API recebe uma solicitação de um aplicativo e a envia para um servidor. O servidor então processa a solicitação e envia os dados de volta para o aplicativo. O aplicativo então interpreta os dados e os apresenta ao usuário.

Um design de arquitetura de API simples

Fonte da imagem: https://www.techfunnel.com/wp-content/uploads/2021/07/api.png

Se quiser saber mais sobre pipelines, APIs e MLOps de aprendizado de máquina, confira nosso Tutorial de aprendizado de máquina, pipelines, implantação e MLOps .

O que é FastAPI

FastAPI é uma estrutura da Web de alto desempenho para criar APIs com Python 3.7+ com base em dicas de tipo Python padrão. Ele ajuda os desenvolvedores a criar aplicativos de forma rápida e eficiente. O FastAPI é construído sobre o servidor da web Starlette e inclui recursos que facilitam a criação de aplicativos da web, como validação automática de dados, tratamento de erros e documentos de API interativos. 

Veremos todos esses recursos individualmente nesta seção. Primeiro, vamos ver os principais recursos indicados na documentação original do FastAPI.

  • Desempenho : No mesmo nível do NodeJS e da linguagem Go.
  • Velocidade : Aumente a velocidade de desenvolvimento 2-3X.
  • Fácil : ótimo suporte ao editor. Conclusão em todos os lugares. Fácil de aprender e usar.
  • Robusto : código pronto para produção com documentação interativa automática.
  • Baseado em OpenAPI : Totalmente compatível com OpenAPI e JSON Schema.

Instalando FastAPI

FastAPI requer Python 3.7+. Pode ser instalado usando pip. Você precisará instalar o FastAPI e o servidor ASGI `uvicorn`.

``

# install fastapi

pip install fastapi




# install uvicorn
pip install uvicorn

``

Crie uma API simples

Vamos começar a criar uma API de brinquedo muito simples. Estou usando o VS Code para implementar isso, mas você pode usar qualquer editor que desejar.

```

from typing import Union

from fastapi import FastAPI




app = FastAPI()




@app.get("")

def read_root():

    return {"Hello": "World"}




@app.get("/items/{item_id}")

def read_item(item_id: int, q: Union[str, None] = None):

    return {"item_id": item_id, "q": q}

```

(Exemplo reproduzido da documentação original ). Obrigado ao @tiangolo.

Agora, usando um terminal de linha de comando, execute esta API com o seguinte comando:

```

uvicorn main:app –reload

```

`main` é o nome do arquivo Python e `app` é a variável que armazena a classe FastAPI. Você pode nomeá-los como quiser. Depois de executar o comando acima, você verá algo assim em seu terminal:

Terminal de comando

Vá até o link em seu navegador e, se vir uma página que mostra "Hello World", a API está funcionando.

API em execução no localhost no navegador

Imagem do autor

Parabéns por criar sua primeira API. 

Documentos API interativos

FastAPI gera um "esquema" com todas as suas APIs usando o padrão OpenAPI para definir APIs. Um "esquema" é uma definição ou descrição de algo. Não o código que o implementa, mas apenas uma descrição abstrata. O esquema OpenAPI é o que alimenta os dois sistemas de documentação interativa incluídos no FastAPI.

Para ver a documentação, basta adicionar `/docs` à url (` http://127.0.0.1:8000/docs `). Este link mostrará a documentação da API interativa automática.

Documentação automatizada criada por FastAPI

Imagem do autor

Clique no botão `Try it out` no canto superior direito para testar a API.

Documentação automatizada criada por FastAPI 2

Imagem do autor

Você pode ver que o corpo da resposta é um dicionário. Esta é a chamada de retorno da função `read_item` definida no `main.py`. Você também pode ver a URL de solicitação `http://127.0.0.1:8000/items/1?q=orange`. `1` e `orange` foram nossas entradas para a API.

Há uma documentação automática interativa alternativa disponível no FastAPI. Para verificar isso, vá para http://127.0.0.1:8000/redoc`. Isto é o que parece:

Documentação automatizada criada por FastAPI 3

Imagem do autor

Exemplos mais avançados

Ao criar uma API, o "caminho" define a rota ou ponto de extremidade da solicitação. No entanto, há mais uma escolha que temos que fazer aqui, ou seja, “Operação”. A palavra `operação` aqui se refere a um dos "métodos" HTTP. Usando um (ou mais) desses chamados "métodos", você pode se comunicar com cada um dos vários caminhos suportados pelo protocolo HTTP. Normalmente, você usaria:

  • POST : para criar dados.
  • GET : para ler os dados.
  • PUT : para atualizar os dados.
  • DELETE : para deletar dados.
  • E alguns outros avançados 

FastAPI suporta todos os métodos http. 

O fato de FastAPI ser construído em dicas de tipo Python é outro aspecto importante dessa estrutura. Dicas de tipo são suportadas em versões do Python 3.6 e posteriores. As dicas de tipo são um tipo especializado de sintaxe que torna possível declarar o tipo de uma variável. 

A declaração de tipos para suas variáveis ​​permite que editores e outras ferramentas forneçam assistência aprimorada. Vejamos um exemplo avançado.

Modificaremos nosso arquivo `main.py` para incluir uma nova solicitação `PUT` que receberá várias entradas de diferentes tipos de dados. 

```

from typing import Union




from fastapi import FastAPI

from pydantic import BaseModel




app = FastAPI()




class Item(BaseModel):

    name: str

    price: float

    is_offer: Union[bool, None] = None




@app.get("")

def read_root():

    return {"Hello": "World"}




@app.get("/items/{item_id}")

def read_item(item_id: int, q: Union[str, None] = None):

    return {"item_id": item_id, "q": q}




@app.put("/items/{item_id}")

def update_item(item_id: int, item: Item):

    return {"item_name": item.name, "item_id": item_id}

```

(Exemplo reproduzido da documentação original ). Obrigado ao @tiangolo.

O troco:

Uma solicitação `put` é adicionada e requer duas entradas. `item_id` é um número inteiro e o tipo `item` está apontando para a classe personalizada `Item` criada e herdando o `BaseModel` de `pydantic`. A classe `Item` contém três atributos: `name`, `price`, `is_offer`, e todos eles possuem diferentes tipos de dados.

FastAPI verificará: 

  • `nome` é um `str`.
  • `price` é um `float`.
  • `is_offer` é um bool, se presente.

O benefício de usar dicas de tipo é que você declara uma vez os tipos de parâmetros, corpo, etc. como parâmetros de função com Python padrão (3.6+). Você vai ter:

  • Suporte ao editor, incluindo preenchimento automático, verificações de tipo
  • Data de validade
  • Conversão de dados de entrada
  • Conversão de dados de saída
  • Erros fáceis de entender.

Comparação de FastAPI com Django e Flask

Todas essas três estruturas são estruturas da Web em Python que você pode usar para desenvolver aplicativos da Web. Cada um deles tem suas próprias forças e fraquezas.

O Django é uma estrutura completa que inclui tudo o que você precisa para começar, incluindo um ORM integrado e um painel de administração. Pode ser um pouco complicado para iniciantes, mas sua documentação abrangente facilita o aprendizado.

O Flask é um microframework leve e fácil de usar. Não inclui tantos recursos quanto o Django, mas é perfeito para projetos simples.

FastAPI é uma nova estrutura projetada para ser rápida e fácil de usar. Inclui recursos como validação automática de dados e documentação. 

 DjangoFrascoFastAPI
Comunidade

Grande. 

66 mil estrelas do GitHub

Grande. 

61 mil estrelas do GitHub

Grande. 

50 mil estrelas do GitHub

DesempenhoDjango é enorme. Não é o melhor em termos de desempenho.Flask é um micro framework web. Ele executa melhor do que o Django.FastAPI é um dos frameworks web mais rápidos com suporte assíncrono nativo que aumenta a eficiência do framework. 
Suporte assíncronoSim, com latência limitada.

Não. 

Necessita Assincio

FastAPI fornece suporte assíncrono nativo.
Fácil de usarDjango é enorme e, portanto, um pouco complicado de aprender.Flask é fácil de aprender e bastante simples de usar.FastAPI é o mais simples de todos os três.
Documentação interativaNão interativoNãoSim (OpenAI, Redoc)
Verificação de dadosNãoNãoSim


Referências de desempenho do FastAPI

De acordo com os resultados dos testes executados pela techempower , o FastAPI é superior a todos os outros frameworks em termos de desempenho geral. 

Referências de desempenho da API

Fonte: https://www.techempower.com/benchmarks/

Exemplo: criar um pipeline de aprendizado de máquina de ponta a ponta com PyCaret e implantar com FastAPI 

Nesta seção, criaremos rapidamente um pipeline de aprendizado de máquina e, em seguida, criaremos uma API para atender ao modelo. Usaremos uma biblioteca Python de baixo código PyCaret para construir um pipeline e criar uma API. PyCaret tem integração com FastAPI, o que torna extremamente fácil criar e servir modelos de aprendizado de máquina como uma API.

PyCaretName

PyCaret é uma biblioteca de aprendizado de máquina de baixo código e código aberto em Python que automatiza fluxos de trabalho de aprendizado de máquina. É uma ferramenta completa de aprendizado de máquina e gerenciamento de modelos que acelera exponencialmente o ciclo de experimentos e o torna mais produtivo.

```

pip install pycaret

```




```

import pycaret

pycaret.__version__

>>> 2.3.10

```

Usaremos o conjunto de dados `insurance` neste exemplo. É um caso de uso de regressão para prever cobranças médicas com base em idade, sexo, IMC e região. 

```

from pycaret.datasets import get_data

data = get_data(‘insurance’)

```

Conjunto de dados de amostra

Imagem do autor

Em seguida, inicializaremos a função `setup` do pycaret. Essa função inicializa o experimento no PyCaret e cria o pipeline de transformação com base em todos os parâmetros passados ​​na função. 

O `setup` deve primeiro ser executado antes de qualquer outra função. Requer dois parâmetros para funcionar `data` e `target`. Todos os argumentos restantes em `setup` são opcionais. A função `setup` é responsável por controlar a totalidade dos procedimentos de pré-processamento de dados. Confira a documentação do PyCaret para obter um resumo abrangente de todos os procedimentos de pré-processamento compatíveis com o PyCaret.

```

from pycaret.regression import *

s = setup(data, target = 'charges')

```

Saída da função de configuração do PyCaret

Imagem do autor Saída truncada.

Once the setup is finished, we can start model training and selection with just one line of code: `compare_models`. Through the use of cross-validation, this function trains and evaluates the model performance of all estimators within the model library. The result of this function is a scoring grid that contains the average scores obtained from cross-validation.
 

```

best = compare_models()

```

Saída da função compare_models do PyCaret

Image by Author

Based on this the best performing model is `Gradient Boosting Regressor`. If we want, we can analyze the model through visualization and further try to improve performance through hyperparameter tuning or model ensembling, but we will not do that in this tutorial. 

We will get straight into building the API of the best model to serve predictions in production using FastAPI. Remember, PyCaret has integration with FastAPI, so it can automatically create a REST API from the model using the `create_api` function.

```

create_api (best, 'insurance_prediction_model')

```

API criada com sucesso

Now to run this API, open the command prompt terminal and navigate to the folder where your Notebook is and run the following command `python insurance_prediction_model.py`. 

Linha de comando

Head over to `http://127.0.0.1:8000/docs` and you will see the same UI as you have seen earlier in this tutorial

API em http:::127.0.0.1:8000:docs

Image by Author

API em http:::127.0.0.18000:docs

Image by Author

You can also see alternative interactive documentation by going to `http://127.0.0.1:8000/redoc

API em http:::127.0.0.1:8000:docs3

Image by Author

Remember, both the default and redoc interactive documentation are powered using OpenAPI standards. 

If you want to see the file that PyCaret created when you used `create_api` function you can check out the file in the same folder as your Notebook. It looks like this:

```

import pandas as pd

from pycaret.regression import load_model, predict_model

from fastapi import FastAPI

import uvicorn




# Create the app

app = FastAPI()




# Load trained Pipeline

model = load_model('my_lr_api')




# Define predict function

@app.post('/predict')

def predict(age, sex, bmi, children, smoker, region):

    data = pd.DataFrame([[age, sex, bmi, children, smoker, region]])

    data.columns = ['age', 'sex', 'bmi', 'children', 'smoker', 'region']

    predictions = predict_model(model, data=data) 

    return {'prediction': list(predictions['Label'])}




if __name__ == '__main__':

    uvicorn.run(app, host='127.0.0.1', port=8000)




```

Conclusion

The article discussed the idea of API and why they are used. API is important in modern architecture because it allows different software programs to share data and functionality. This makes it possible to create complex systems that are more reliable and easier to maintain.

We then deep dive into a relatively new framework in Python called FastAPI. FastAPI is a newer API that is designed to be easy to use and efficient. It is a great option for developers who want to create an API quickly and easily.

GitHub star history - criado usando star-history.com

GitHub star history - created using star-history.com

If you also want to learn how to create a simple API from a machine learning model in Python using Flask,

Fonte do artigo original em: https://www.datacamp.com

#python  #fastapi 

Uma introdução ao uso do FastAPI em Python
Duong Tran

Duong Tran

1680680520

Giới thiệu về cách sử dụng FastAPI trong Python

Trong hướng dẫn FastAPI này, chúng ta sẽ tìm hiểu về Hướng dẫn FastAPI: Giới thiệu về cách sử dụng FastAPI trong Python. API (Giao diện lập trình ứng dụng) là xương sống của kiến ​​trúc hiện đại vì chúng cho phép các ứng dụng được mô-đun hóa và tách rời. Điều này có nghĩa là bạn có thể xây dựng các ứng dụng được xây dựng nhanh chóng và dễ dàng, cho phép bạn dễ dàng bảo trì và cập nhật chúng. 

API cũng rất quan trọng trong học máy vì chúng cho phép các ứng dụng khác nhau chia sẻ dữ liệu và làm việc cùng nhau, tiết kiệm thời gian và công sức. Có nhiều khung khác nhau để xây dựng API bằng Python. Một số khung phổ biến nhất để tạo API trong Python là Django, Flask và FastAPI. Hướng dẫn này đi sâu vào một trong những khung có tên là FastAPI.

API là gì?

API là viết tắt của Giao diện lập trình ứng dụng. API là một trung gian phần mềm cho phép hai ứng dụng nói chuyện với nhau. Khi bạn sử dụng một ứng dụng trên điện thoại, ứng dụng đó sẽ kết nối với Internet và gửi dữ liệu đến một máy chủ. Sau đó, máy chủ sẽ xử lý dữ liệu và gửi lại cho điện thoại của bạn. Sau đó, ứng dụng trên điện thoại của bạn sẽ diễn giải dữ liệu và trình bày cho bạn theo cách có thể đọc được. 

API giống như người phục vụ trong nhà hàng. Người phục vụ nhận đơn đặt hàng của bạn và gửi nó đến nhà bếp. Nhà bếp sau đó chuẩn bị thức ăn và gửi lại cho người phục vụ. Người phục vụ sau đó mang thức ăn đến cho bạn. 

Theo cách tương tự, API nhận yêu cầu từ ứng dụng và gửi yêu cầu đó đến máy chủ. Sau đó, máy chủ sẽ xử lý yêu cầu và gửi dữ liệu trở lại ứng dụng. Sau đó, ứng dụng sẽ diễn giải dữ liệu và trình bày cho người dùng.

Một thiết kế kiến ​​trúc API đơn giản

Nguồn hình ảnh: https://www.techfunnel.com/wp-content/uploads/2021/07/api.png

Nếu muốn tìm hiểu thêm về quy trình máy học, API và MLOps, bạn có thể xem Hướng dẫn về máy học, quy trình, triển khai và MLOps của chúng tôi .

FastAPI là gì

FastAPI là một khung web hiệu suất cao để xây dựng API với Python 3.7+ dựa trên các gợi ý loại Python tiêu chuẩn. Nó giúp các nhà phát triển xây dựng các ứng dụng một cách nhanh chóng và hiệu quả. FastAPI được xây dựng trên máy chủ web Starlette và bao gồm các tính năng giúp xây dựng ứng dụng web dễ dàng hơn, chẳng hạn như xác thực dữ liệu tự động, xử lý lỗi và tài liệu API tương tác. 

Chúng tôi sẽ xem xét tất cả các tính năng này một cách riêng lẻ trong phần này. Trước tiên, hãy xem xét các tính năng chính như được chỉ ra trong tài liệu gốc của FastAPI.

  • Hiệu suất : Ngang bằng với NodeJS và ngôn ngữ Go.
  • Tốc độ : Tăng tốc độ phát triển lên 2-3 lần.
  • Dễ dàng : Hỗ trợ trình chỉnh sửa tuyệt vời. Hoàn thành ở khắp mọi nơi. Dễ dàng để tìm hiểu và sử dụng.
  • Mạnh mẽ : Mã sẵn sàng sản xuất với tài liệu tương tác tự động.
  • Dựa trên OpenAPI : Hoàn toàn tương thích với OpenAPI và Lược đồ JSON.

Cài đặt FastAPI

FastAPI yêu cầu Python 3.7 trở lên. Nó có thể được cài đặt bằng pip. Bạn sẽ cần cài đặt FastAPI và máy chủ ASGI `uvicorn`.

``

# install fastapi

pip install fastapi




# install uvicorn
pip install uvicorn

``

Tạo một API đơn giản

Hãy trực tiếp tạo một API đồ chơi rất đơn giản. Tôi đang sử dụng Mã VS để thực hiện điều này, nhưng bạn có thể sử dụng bất kỳ trình chỉnh sửa nào bạn muốn.

```

from typing import Union

from fastapi import FastAPI




app = FastAPI()




@app.get("")

def read_root():

    return {"Hello": "World"}




@app.get("/items/{item_id}")

def read_item(item_id: int, q: Union[str, None] = None):

    return {"item_id": item_id, "q": q}

```

(Ví dụ sao chép từ tài liệu gốc ). Cảm ơn @tiangolo.

Hiện đang sử dụng thiết bị đầu cuối dòng lệnh, hãy chạy API này bằng lệnh sau:

```

uvicorn main:app –reload

```

`main` là tên của tệp Python và `app` là biến lưu trữ lớp FastAPI. Bạn có thể đặt tên cho chúng bất cứ điều gì bạn thích. Khi bạn chạy lệnh trên, bạn sẽ thấy một cái gì đó như thế này trên thiết bị đầu cuối của mình:

Trạm chỉ huy

Đi tới liên kết trong trình duyệt của bạn và nếu bạn thấy một trang hiển thị `Xin chào thế giới`, thì API đã hoạt động.

API chạy trên localhost trong trình duyệt

Hình ảnh của tác giả

Chúc mừng bạn đã xây dựng API đầu tiên của mình. 

Tài liệu API tương tác

FastAPI tạo một "lược đồ" với tất cả các API của bạn bằng cách sử dụng tiêu chuẩn OpenAPI để xác định API. Một "lược đồ" là một định nghĩa hoặc mô tả về một cái gì đó. Không phải mã triển khai nó, mà chỉ là một mô tả trừu tượng. Lược đồ OpenAPI là thứ cung cấp năng lượng cho hai hệ thống tài liệu tương tác có trong FastAPI.

Để xem tài liệu, chỉ cần thêm `/docs` vào url (` http://127.0.0.1:8000/docs `). Liên kết này sẽ hiển thị tài liệu API tương tác tự động.

Tài liệu tự động được tạo bởi FastAPI

Hình ảnh của tác giả

Nhấp vào nút `Dùng thử` ở góc trên cùng bên phải để kiểm tra API.

Tài liệu tự động được tạo bởi FastAPI 2

Hình ảnh của tác giả

Bạn có thể thấy nội dung phản hồi là một từ điển. Đây là lệnh gọi trả về của hàm `read_item` được xác định trong `main.py`. Bạn cũng có thể xem url yêu cầu `http://127.0.0.1:8000/items/1?q=orange`. `1` và `orange` là đầu vào của chúng tôi cho API.

Có một tài liệu tự động tương tác thay thế có sẵn trong FastAPI. Để kiểm tra điều đó, hãy truy cập http://127.0.0.1:8000/redoc`. Đây là những gì nó trông giống như:

Tài liệu tự động được tạo bởi FastAPI 3

Hình ảnh của tác giả

Ví dụ nâng cao hơn

Trong khi xây dựng API, "đường dẫn" xác định tuyến đường hoặc điểm cuối của yêu cầu. Tuy nhiên, có một sự lựa chọn nữa mà chúng ta phải thực hiện ở đây, tức là “Chiến dịch”. Từ `hoạt động` ở đây đề cập đến một trong các "phương thức" HTTP. Bằng cách sử dụng một (hoặc nhiều) cái gọi là "phương thức" này, bạn có thể giao tiếp với từng đường dẫn được giao thức HTTP hỗ trợ. Thông thường, bạn sẽ sử dụng:

  • POST : để tạo dữ liệu.
  • GET : để đọc dữ liệu.
  • PUT : để cập nhật dữ liệu.
  • XÓA : để xóa dữ liệu.
  • Và một số cái nâng cao khác 

FastAPI hỗ trợ tất cả các phương thức http. 

Việc FastAPI được xây dựng dựa trên các gợi ý kiểu Python là một khía cạnh quan trọng khác của khung này. Gợi ý nhập được hỗ trợ trong các phiên bản Python 3.6 trở lên. Các gợi ý kiểu là một loại cú pháp chuyên dụng cho phép khai báo kiểu của một biến. 

Việc khai báo các loại biến cho phép trình chỉnh sửa và các công cụ khác hỗ trợ tốt hơn cho bạn. Hãy xem một ví dụ nâng cao.

Chúng tôi sẽ sửa đổi tệp `main.py` của mình để bao gồm một yêu cầu `PUT` mới sẽ nhận nhiều đầu vào thuộc các loại dữ liệu khác nhau. 

```

from typing import Union




from fastapi import FastAPI

from pydantic import BaseModel




app = FastAPI()




class Item(BaseModel):

    name: str

    price: float

    is_offer: Union[bool, None] = None




@app.get("")

def read_root():

    return {"Hello": "World"}




@app.get("/items/{item_id}")

def read_item(item_id: int, q: Union[str, None] = None):

    return {"item_id": item_id, "q": q}




@app.put("/items/{item_id}")

def update_item(item_id: int, item: Item):

    return {"item_name": item.name, "item_id": item_id}

```

(Ví dụ sao chép từ tài liệu gốc ). Cảm ơn @tiangolo.

Sự thay đổi:

Yêu cầu `put` được thêm vào có hai đầu vào. `item_id` là một số nguyên và loại `item` trỏ đến lớp tùy chỉnh`Item` được tạo và kế thừa `BaseModel` từ `pydantic`. Lớp `Mặt hàng` chứa ba thuộc tính: `tên`, `giá`, `giá_ưu_đãi` và tất cả các thuộc tính này đều có các loại dữ liệu khác nhau.

FastAPI sẽ kiểm tra: 

  • `tên` là một `str`.
  • `giá` là `thả nổi`.
  • `is_offer` là một bool, nếu có.

Lợi ích của việc sử dụng gợi ý kiểu là bạn khai báo một lần các kiểu tham số, nội dung, v.v. dưới dạng tham số hàm với Python tiêu chuẩn (3.6+). Bạn sẽ nhận được:

  • Hỗ trợ trình chỉnh sửa, bao gồm tự động hoàn thành, kiểm tra loại
  • Xác nhận dữ liệu
  • Chuyển đổi dữ liệu đầu vào
  • Chuyển đổi dữ liệu đầu ra
  • Các lỗi dễ hiểu.

So sánh FastAPI với Django và Flask

Cả ba khung này đều là các khung web Python mà bạn có thể sử dụng để phát triển các ứng dụng web. Họ đều có điểm mạnh và điểm yếu riêng.

Django là một khung đầy đủ tính năng bao gồm mọi thứ bạn cần để bắt đầu, bao gồm ORM tích hợp sẵn và bảng điều khiển quản trị. Nó có thể hơi khó đối với người mới bắt đầu, nhưng tài liệu toàn diện của nó giúp bạn dễ dàng tìm hiểu.

Flask là một microframework nhẹ và dễ bắt đầu. Nó không bao gồm nhiều tính năng như Django, nhưng nó hoàn hảo cho các dự án đơn giản.

FastAPI là một khung mới được thiết kế để hoạt động nhanh và dễ sử dụng. Nó bao gồm các tính năng như tài liệu và xác thực dữ liệu tự động. 

 DjangoBình giữ nhiệtAPI nhanh
Cộng đồng

To lớn. 

66K sao GitHub

To lớn. 

61 nghìn sao GitHub

To lớn. 

50 nghìn sao GitHub

Hiệu suấtDjango rất lớn. Nó không phải là tốt nhất về hiệu suất.Flask là một khung web vi mô. Nó hoạt động tốt hơn Django.FastAPI là một trong những khung web nhanh nhất có hỗ trợ async gốc giúp tăng thêm hiệu quả của khung. 
hỗ trợ không đồng bộCó, với độ trễ hạn chế.

KHÔNG. 

Cần Asyncio

FastAPI cung cấp hỗ trợ không đồng bộ gốc.
Dễ sử dụngDjango rất lớn và do đó hơi phức tạp để học.Flask rất dễ học và sử dụng khá đơn giản.FastAPI là đơn giản nhất trong cả ba.
Tài liệu tương tácKhông tương tácKHÔNGCó (OpenAI, Redoc)
Xác minh dữ liệuKHÔNGKHÔNGĐúng


Điểm chuẩn hiệu suất FastAPI

Theo kết quả kiểm tra do techempower thực hiện , FastAPI vượt trội hơn tất cả các khung khác về hiệu suất tổng thể của nó. 

Điểm chuẩn hiệu suất API

Nguồn: https://www.techempower.com/benchmarks/

Ví dụ: Xây dựng Đường ống học máy từ đầu đến cuối với PyCaret và triển khai với FastAPI 

Trong phần này, chúng ta sẽ nhanh chóng xây dựng một quy trình học máy và sau đó tạo một API để phục vụ mô hình. Chúng tôi sẽ sử dụng thư viện Python mã thấp PyCaret để xây dựng đường dẫn và tạo API. PyCaret đã tích hợp với FastAPI, giúp tạo và phục vụ các mô hình máy học dưới dạng API cực kỳ dễ dàng.

PyCaret

PyCaret là một thư viện máy học mã nguồn mở, ít mã trong Python giúp tự động hóa quy trình học máy. Nó là một công cụ quản lý mô hình và học máy từ đầu đến cuối giúp tăng tốc chu kỳ thử nghiệm theo cấp số nhân và giúp bạn làm việc hiệu quả hơn.

```

pip install pycaret

```




```

import pycaret

pycaret.__version__

>>> 2.3.10

```

Chúng tôi sẽ sử dụng bộ dữ liệu `bảo hiểm` trong ví dụ này. Đây là trường hợp sử dụng hồi quy để dự đoán chi phí y tế dựa trên độ tuổi, giới tính, BMI và khu vực. 

```

from pycaret.datasets import get_data

data = get_data(‘insurance’)

```

Tập dữ liệu mẫu

Hình ảnh của tác giả

Tiếp theo chúng ta sẽ khởi tạo hàm `setup` từ pycaret. Hàm này khởi tạo thử nghiệm trong PyCaret và tạo quy trình chuyển đổi dựa trên tất cả các tham số được truyền trong hàm. 

`thiết lập` trước tiên phải được thực hiện trước bất kỳ chức năng nào khác. Nó yêu cầu hai tham số để hoạt động là `dữ liệu` và `mục tiêu`. Tất cả các đối số còn lại trong `thiết lập` là tùy chọn. Chức năng `thiết lập` chịu trách nhiệm kiểm soát toàn bộ quy trình tiền xử lý dữ liệu. Hãy xem tài liệu PyCaret để biết tóm tắt toàn diện về tất cả các quy trình tiền xử lý được hỗ trợ trong PyCaret.

```

from pycaret.regression import *

s = setup(data, target = 'charges')

```

Đầu ra từ chức năng thiết lập của PyCaret

Hình ảnh của Tác giả Đầu ra bị cắt bớt.

Sau khi thiết lập xong, chúng ta có thể bắt đầu đào tạo và lựa chọn mô hình chỉ bằng một dòng mã: `so sánh_models`. Thông qua việc sử dụng xác thực chéo, chức năng này đào tạo và đánh giá hiệu suất mô hình của tất cả các công cụ ước tính trong thư viện mô hình. Kết quả của chức năng này là một lưới tính điểm có chứa điểm trung bình thu được từ xác thực chéo.
 

```

best = compare_models()

```

Đầu ra từ hàm so sánh_models của PyCaret

Hình ảnh của tác giả

Dựa trên điều này, mô hình hoạt động tốt nhất là `Gradient Boosting Regressor`. Nếu muốn, chúng ta có thể phân tích mô hình thông qua trực quan hóa và cố gắng cải thiện hiệu suất hơn nữa thông qua điều chỉnh siêu tham số hoặc tập hợp mô hình, nhưng chúng ta sẽ không làm điều đó trong hướng dẫn này. 

Chúng tôi sẽ đi thẳng vào việc xây dựng API của mô hình tốt nhất để phục vụ các dự đoán trong quá trình sản xuất bằng FastAPI. Hãy nhớ rằng PyCaret đã tích hợp với FastAPI, do đó, nó có thể tự động tạo API REST từ mô hình bằng cách sử dụng chức năng `create_api`.

```

create_api (best, 'insurance_prediction_model')

```

API được tạo thành công

Bây giờ để chạy API này, hãy mở terminal nhắc lệnh và điều hướng đến thư mục chứa Notebook của bạn và chạy lệnh sau `pythonBH_prediction_model.py`. 

Dòng lệnh

Truy cập `http://127.0.0.1:8000/docs` và bạn sẽ thấy giao diện người dùng giống như bạn đã thấy trước đó trong hướng dẫn này

API trên http:::127.0.0.1:8000:docs

Hình ảnh của tác giả

API trên http:::127.0.0.18000:docs

Hình ảnh của tác giả

Bạn cũng có thể xem tài liệu tương tác thay thế bằng cách truy cập ` http://127.0.0.1:8000/redoc '

API trên http:::127.0.0.1:8000:docs3

Hình ảnh của tác giả

Hãy nhớ rằng, cả tài liệu tương tác mặc định và chỉnh sửa lại đều được hỗ trợ bằng các tiêu chuẩn OpenAPI. 

Nếu bạn muốn xem tệp mà PyCaret đã tạo khi bạn sử dụng chức năng `create_api`, bạn có thể kiểm tra tệp trong cùng thư mục với Notebook của mình. Nó trông như thế này:

```

import pandas as pd

from pycaret.regression import load_model, predict_model

from fastapi import FastAPI

import uvicorn




# Create the app

app = FastAPI()




# Load trained Pipeline

model = load_model('my_lr_api')




# Define predict function

@app.post('/predict')

def predict(age, sex, bmi, children, smoker, region):

    data = pd.DataFrame([[age, sex, bmi, children, smoker, region]])

    data.columns = ['age', 'sex', 'bmi', 'children', 'smoker', 'region']

    predictions = predict_model(model, data=data) 

    return {'prediction': list(predictions['Label'])}




if __name__ == '__main__':

    uvicorn.run(app, host='127.0.0.1', port=8000)




```

Phần kết luận

Bài viết đã thảo luận về ý tưởng của API và lý do tại sao chúng được sử dụng. API rất quan trọng trong kiến ​​trúc hiện đại vì nó cho phép các chương trình phần mềm khác nhau chia sẻ dữ liệu và chức năng. Điều này cho phép tạo ra các hệ thống phức tạp, đáng tin cậy hơn và dễ bảo trì hơn.

Sau đó, chúng tôi đi sâu vào một khung tương đối mới trong Python có tên là FastAPI. FastAPI là một API mới hơn được thiết kế để dễ sử dụng và hiệu quả. Đây là một lựa chọn tuyệt vời cho các nhà phát triển muốn tạo API một cách nhanh chóng và dễ dàng.

Lịch sử sao GitHub - được tạo bằng star-history.com

Lịch sử sao GitHub - được tạo bằng star-history.com

Nếu bạn cũng muốn tìm hiểu cách tạo API đơn giản từ mô hình máy học trong Python bằng Flask,

Nguồn bài viết gốc tại: https://www.datacamp.com

#python  #fastapi 

Giới thiệu về cách sử dụng FastAPI trong Python
Rylan  Becker

Rylan Becker

1680501900

An Introduction to Using FastAPI In Python

In this FastAPI tutorial, we will learn about FastAPI Tutorial: An Introduction to Using FastAPI in Python. API (Application Programming Interface) are the backbone of modern architecture because they allow for applications to be modular and decoupled. This means that you can build applications built quickly and easily, allowing you to easily maintain and update them. 

APIs are also very important in machine learning because they allow different applications to share data and work together, saving time and effort. There are many different frameworks for building APIs in Python. Some of the most popular frameworks for creating APIs in Python are Django, Flask, and FastAPI. This tutorial is a deep dive into one of the frameworks called FastAPI.

What is an API?

API stands for Application Programming Interface. An API is a software intermediary that allows two applications to talk to each other. When you use an application on your phone, the application connects to the Internet and sends data to a server. The server then processes the data and sends it back to your phone. The application on your phone then interprets the data and presents it to you in a readable way. 

An API is like a waiter in a restaurant. The waiter takes your order and sends it to the kitchen. The kitchen then prepares the food and sends it back to the waiter. The waiter then brings the food to you. 

In the same way, an API takes a request from an application and sends it to a server. The server then processes the request and sends the data back to the application. The application then interprets the data and presents it to the user.

A simple API architecture design

Image Source: https://www.techfunnel.com/wp-content/uploads/2021/07/api.png

If you want to learn more about machine learning pipelines, APIs, and MLOps, you can check out our Machine Learning, Pipelines, Deployment and MLOps Tutorial.

What is FastAPI

FastAPI is a high-performing web framework for building APIs with Python 3.7+ based on standard Python type hints. It helps developers build applications quickly and efficiently. FastAPI is built on top of the Starlette web server and includes features that make building web applications easier, such as automatic data validation, error handling, and interactive API docs. 

We will look at all these features individually in this section. First, let’s look at key features as pointed out in the original documentation of FastAPI.

  • Performance: On par with NodeJS and the Go language.
  • Speed: Increase the development speed 2-3X.
  • Easy: Great editor support. Completion everywhere. Easy to learn and use.
  • Robust: Production-ready code with automatic interactive documentation.
  • OpenAPI based: Fully compatible with OpenAPI and JSON Schema.

Installing FastAPI

FastAPI requires Python 3.7+. It can be installed using pip. You will need to install FastAPI and the ASGI server `uvicorn`.

``

# install fastapi

pip install fastapi




# install uvicorn
pip install uvicorn

``

Create a simple API

Let’s directly get into creating a very simple toy API. I am using VS Code to implement this, but you can use any editor you like.

```

from typing import Union

from fastapi import FastAPI




app = FastAPI()




@app.get("")

def read_root():

    return {"Hello": "World"}




@app.get("/items/{item_id}")

def read_item(item_id: int, q: Union[str, None] = None):

    return {"item_id": item_id, "q": q}

```

(Example reproduced from the original documentation). Thanks to @tiangolo.

Now using a command line terminal, run this API with the following command:

```

uvicorn main:app –reload

```

`main` is the name of the Python file, and `app` is the variable that stores the FastAPI class. You can name them whatever you like. Once you run the above command, you will see something like this on your terminal:

Command Terminal

Head over to the link in your browser, and if you see a page that shows `Hello World,` the API is up and running.

API running on localhost in browser

Image by Author

Congratulations on building your first API. 

Interactive API Docs

FastAPI generates a "schema" with all your APIs using the OpenAPI standard for defining APIs. A "schema" is a definition or description of something. Not the code that implements it, but just an abstract description. The OpenAPI schema is what powers the two interactive documentation systems included in FastAPI.

To see the documentation, just add `/docs` to the url (`http://127.0.0.1:8000/docs`). This link will show automatic interactive API documentation.

Automated documentation created by FastAPI

Image by Author

Click on `Try it out` button in the top right corner to test the API.

Automated documentation created by FastAPI 2

Image by Author

You can see the response body is a dictionary. This is the return call of the `read_item` function defined in the `main.py`. You can also see the request url `http://127.0.0.1:8000/items/1?q=orange`. `1` and `orange` were our inputs to the API.

There is an alternative interactive automatic documentation available in FastAPI. To check that out, go to http://127.0.0.1:8000/redoc`. This is what it looks like:

Automated documentation created by FastAPI 3

Image by Author

More advanced examples

While building an API, the "path" defines the route or endpoint of the request. However, there is one more choice we have to make here, i.e., “Operation.” The word `operation` here refers to one of the HTTP "methods." By using one (or more) of these so-called "methods," you can communicate with each of the several paths supported by the HTTP protocol. Typically, you would use:

  • POST: to create data.
  • GET: to read data.
  • PUT: to update data.
  • DELETE: to delete data.
  • And a few other advanced ones 

FastAPI supports all of the http methods. 

The fact that FastAPI is built on Python type hints is yet another key aspect of this framework. Type hints are supported in versions of Python 3.6 and later. The type hints are a specialized kind of syntax that makes it possible to declare the type of a variable. 

Declaring types for your variables enables editors and other tools to provide you with improved assistance. Let’s see an advanced example.

We will modify our `main.py` file to include a new `PUT` request which will take multiple inputs of different data types. 

```

from typing import Union




from fastapi import FastAPI

from pydantic import BaseModel




app = FastAPI()




class Item(BaseModel):

    name: str

    price: float

    is_offer: Union[bool, None] = None




@app.get("")

def read_root():

    return {"Hello": "World"}




@app.get("/items/{item_id}")

def read_item(item_id: int, q: Union[str, None] = None):

    return {"item_id": item_id, "q": q}




@app.put("/items/{item_id}")

def update_item(item_id: int, item: Item):

    return {"item_name": item.name, "item_id": item_id}

```

(Example reproduced from the original documentation). Thanks to @tiangolo.

The change:

A `put` request is added that takes two inputs. `item_id` is an integer and `item` type is pointing to custom class`Item` created and inheriting the `BaseModel` from `pydantic`. The class `Item` contains three attributes: `name`, `price`, `is_offer`, and all of them have different data types.

FastAPI will check: 

  • `name` is a `str`.
  • `price` is a `float`.
  • `is_offer` is a bool, if present.

The benefit of using type hints is that you declare once the types of parameters, body, etc. as function parameters with standard Python (3.6+). You will get:

  • Editor support, including auto-completion, type checks
  • Data Validation
  • Conversion of input data
  • Conversion of output data
  • Errors that are easy to understand.

Comparison of FastAPI with Django and Flask

All three of these frameworks are Python web frameworks that you can use to develop web applications. They each have their own strengths and weaknesses.

Django is a full-featured framework that includes everything you need to get started, including a built-in ORM and an admin panel. It can be a bit overwhelming for beginners, but its comprehensive documentation makes it easy to learn.

Flask is a microframework that is lightweight and easy to get started with. It doesn't include as many features as Django, but it's perfect for simple projects.

FastAPI is a new framework that is designed to be fast and easy to use. It includes features like automatic data validation and documentation. 

 DjangoFlaskFastAPI
Community

Big. 

66K GitHub stars

Big. 

61K GitHub stars

Big. 

50K GitHub stars

PerformanceDjango is massive. It isn't the best in terms of performance.Flask is a micro web framework. It performs better than Django.FastAPI is one of the fastest web frameworks with native async support that adds to the efficiency of the framework. 
Async supportYes, with limited latency.

No. 

Needs Asyncio

FastAPI provides native async support.
Ease of useDjango is massive and hence a bit complicated to learn.Flask is easy to learn and pretty straightforward in use.FastAPI is the simplest of all three.
Interactive DocumentationNot interactiveNoYes (OpenAI, Redoc)
Data VerificationNoNoYes


FastAPI Performance Benchmarks

According to the results of tests run by techempower, FastAPI is superior to all other frameworks in terms of its overall performance. 

API Performance benchmarks

Source: https://www.techempower.com/benchmarks/

Example: Building an end-to-end machine learning Pipeline with PyCaret and deploying with FastAPI 

In this section, we will quickly build a machine learning pipeline and then create an API to serve the model. We will use a low-code Python library PyCaret to build a pipeline and create an API. PyCaret has integration with FastAPI, which makes it extremely easy to create and serve machine learning models as an API.

PyCaret

PyCaret is an open-source, low-code machine learning library in Python that automates machine learning workflows. It is an end-to-end machine learning and model management tool that speeds up the experiment cycle exponentially and makes you more productive.

```

pip install pycaret

```




```

import pycaret

pycaret.__version__

>>> 2.3.10

```

We will use the `insurance` dataset in this example. It is a regression use-case for predicting medical charges based on age, sex, BMI, and region. 

```

from pycaret.datasets import get_data

data = get_data(‘insurance’)

```

Sample Dataset

Image by Author

Next we will initialize the `setup` function from pycaret. This function initializes the experiment in PyCaret and creates the transformation pipeline based on all the parameters passed in the function. 

The `setup` must first executed before any other function. It requires two parameters to work `data` and `target`. All the remaining arguments in `setup` are optional. The `setup` function is responsible for controlling the entirety of the data preprocessing procedures. Check out the PyCaret documentation for a comprehensive rundown of all of the preprocessing procedures that are supported in PyCaret.

```

from pycaret.regression import *

s = setup(data, target = 'charges')

```

Output from the setup function of PyCaret

Image by Author Output truncated.

Once the setup is finished, we can start model training and selection with just one line of code: `compare_models`. Through the use of cross-validation, this function trains and evaluates the model performance of all estimators within the model library. The result of this function is a scoring grid that contains the average scores obtained from cross-validation.
 

```

best = compare_models()

```

Output from the compare_models function of PyCaret

Image by Author

Based on this the best performing model is `Gradient Boosting Regressor`. If we want, we can analyze the model through visualization and further try to improve performance through hyperparameter tuning or model ensembling, but we will not do that in this tutorial. 

We will get straight into building the API of the best model to serve predictions in production using FastAPI. Remember, PyCaret has integration with FastAPI, so it can automatically create a REST API from the model using the `create_api` function.

```

create_api (best, 'insurance_prediction_model')

```

API Sucessfully Created

Now to run this API, open the command prompt terminal and navigate to the folder where your Notebook is and run the following command `python insurance_prediction_model.py`. 

Command Line

Head over to `http://127.0.0.1:8000/docs` and you will see the same UI as you have seen earlier in this tutorial

API on http:::127.0.0.1:8000:docs

Image by Author

API on http:::127.0.0.18000:docs

Image by Author

You can also see alternative interactive documentation by going to `http://127.0.0.1:8000/redoc

API on http:::127.0.0.1:8000:docs3

Image by Author

Remember, both the default and redoc interactive documentation are powered using OpenAPI standards. 

If you want to see the file that PyCaret created when you used `create_api` function you can check out the file in the same folder as your Notebook. It looks like this:

```

import pandas as pd

from pycaret.regression import load_model, predict_model

from fastapi import FastAPI

import uvicorn




# Create the app

app = FastAPI()




# Load trained Pipeline

model = load_model('my_lr_api')




# Define predict function

@app.post('/predict')

def predict(age, sex, bmi, children, smoker, region):

    data = pd.DataFrame([[age, sex, bmi, children, smoker, region]])

    data.columns = ['age', 'sex', 'bmi', 'children', 'smoker', 'region']

    predictions = predict_model(model, data=data) 

    return {'prediction': list(predictions['Label'])}




if __name__ == '__main__':

    uvicorn.run(app, host='127.0.0.1', port=8000)




```

Conclusion

The article discussed the idea of API and why they are used. API is important in modern architecture because it allows different software programs to share data and functionality. This makes it possible to create complex systems that are more reliable and easier to maintain.

We then deep dive into a relatively new framework in Python called FastAPI. FastAPI is a newer API that is designed to be easy to use and efficient. It is a great option for developers who want to create an API quickly and easily.

GitHub star history - created using star-history.com

GitHub star history - created using star-history.com

If you also want to learn how to create a simple API from a machine learning model in Python using Flask,

Original article source at: https://www.datacamp.com

#python #fastapi 

An Introduction to Using FastAPI In Python
Yvette  Bell

Yvette Bell

1680350700

Sociome: API using python and Fastapi framework

Welcome 👋

Sociome is a API DEVELOPMENT PROJECT UNDER CODE FOR COMMUNITY ! capable of CRUD operation and this api is specific with Social Media Application Functionalities.

Tech-Stacks Used 🔮

Project Walkthrough 🚀

Installation ☘️

To install The Fastapi on the system

pip install fastapi

To install all the dependiencies at once use :

pip install fastapi[all]

 

Run the server in LocalHost:

uvicorn main:app --reload

Open your browser at !

http://127.0.0.1:8000/

Interactive API doc

http://127.0.0.1:8000/docs 

Sample code 🛠

import datetime from typing import Optional import time from datetime import date, time,datetime from fastapi import FastAPI app = FastAPI() @app.get("/") def read_root():    return {"Messgaes": "Hey viewer ! i made it man !","Author":"Abhishek Kushwaha"} @app.get("/items/{item_id}") def read_item(item_id: int, q: Optional[str] = None):    return {"item_id": item_id, "q": q} @app.get("/author/{author_id}/{q}") def read_item(author_id: int, q: Optional[str] = None):    return {"item_id": author_id, "request": q ,"name":"Abhishek kushwaha"}

🙏 Support

-This project needs a ⭐️ from you. Don't forget to leave a star ⭐️

-Follow me here

-Contributions to the project are most welcome! 😊

-Feel free to fork this repo and contribute. 🔧

-Thank You!👍


Download details:

Author: Abbhiishek
Source: https://github.com/Abbhiishek/Sociome

License: MIT license

#python #fastapi 

Sociome: API using python and Fastapi framework
Yvette  Bell

Yvette Bell

1680343260

Fastapi-event: Event Dispatcher for FastAPI Framework

fastapi-event


fastapi-event is event dispatcher for FastAPI framework.

Installation

pip3 install fastapi-event

Usage

Make Event

from fastapi_event import BaseEvent


class TestEvent(BaseEvent):
    async def run(self, parameter=None):
        ...

Inherit BaseEvent and override run() method.

from fastapi_event import BaseEvent


class FirstEvent(BaseEvent):
    ORDER = 1  # HERE(Optional)
    
    async def run(self, parameter=None):
        ...


class SecondEvent(BaseEvent):
    ORDER = 2  # HERE(Optional)
    
    async def run(self, parameter=None):
        ...

If you want to determine the order between events, specify ORDER in your event.

Then, regardless of the order in which the events are stored, they will be executed in the order specified in ORDER variable.

However, ORDER does not work when run_at_once=True.

Parameter(optional)

from pydantic import BaseModel


class TestEventParameter(BaseModel):
    id: str
    pw: str

In case of need parameter, you have to inherit BaseModel and set fields.

Middleware

from fastapi import FastAPI
from fastapi_event import EventHandlerMiddleware

app = FastAPI()
app.add_middleware(EventHandlerMiddleware)

EventListener

from fastapi_event import EventListener


@EventListener()
async def test():
    ...

Set @EventListener() decorator on the function that emits the event.

@EventListener(run_at_once=False)

If you pass run_at_once=False, it will execute in the order in which store() is called. (or according to the ORDER variable defined in the event)

Otherwise, it will execute through asyncio.gather() to run at once.

Store event

from fastapi_event import EventListener, event_handler


@EventListener()
async def test():
    await event_handler.store(
        event=TestEvent,
        parameter=TestParameter(id="hide", pw="hide"),  # Optional
    )

Store your event to handler via store() method. (parameter is optional)

An event will be emitted after the function has finished executing.


Download details:

Author: teamhide
Source: https://github.com/teamhide/fastapi-event

License: Apache-2.0 license

#python #fastapi 

Fastapi-event: Event Dispatcher for FastAPI Framework
Yvette  Bell

Yvette Bell

1680339480

FastLab: An extension library for FastAPI framework | Python

FastLab

An extension library for FastAPI framework

Installation

use pip to install the package:

pip install fastlab

Getting started

Logging

Easy to log string to console, see more: https://docs.python.org/3/library/logging.html

from fastlab import logs

logs.warning('warn')    # 2021-12-18 14:23:31.000  WARNING 88493 --- [  MainThread] test_logs        : warn
logs.info('info')       # 2021-12-18 14:23:31.000     INFO 88493 --- [  MainThread] test_logs        : info
logs.error('error')     # 2021-12-18 14:23:31.000    ERROR 88493 --- [  MainThread] test_logs        : error

Models

Common Models

🔰 Response

from fastapi import FastAPI
from pydantic import BaseModel
from fastlab.models import Response


class Item(BaseModel):
    name: str
    version: str


app = FastAPI()


@app.get("/item", response_model=Response[Item])
async def item():
    return Response(data=Item(name='fastlab', version='0.1.0'))

Get http://localhost:8080/item response:

{
    "code": 0,
    "message": "",
    "data": {
        "name": "fastlab",
        "version": "0.1.0"
    }
}

🔰 PageData

from fastapi import FastAPI
from pydantic import BaseModel
from fastlab.models import Response, PageData


class Item(BaseModel):
    name: str
    version: str


app = FastAPI()


@app.get("/items", response_model=Response[PageData[Item]])
async def items(skip: int = 0, limit: int = 10):
    total = 100
    data = [Item(name=f'fastlab-{i}', version=f'0.1.{i}') for i in range(skip, skip + limit)]
    return Response(data=PageData(skip=skip, limit=limit, total=total, has_more=total > skip + limit, data=data))

Utils

🔰 TimeUtils

from fastlab.utils import TimeUtils

# Print now timestamp: 1639732030521
print(TimeUtils.timestamp())

Routers

🔰 HealthRouter

API for health check, endpoint /health.

from fastapi import FastAPI
from fastlab.routers import HealthRouter

app = FastAPI()
app.include_router(HealthRouter)

Decorators

🔰 WithEnvConfig

Replace the configuration with system environment variables. Follows:

  1. Change the setting name to uppercase
  2. Prefix it with prefix setting
  3. Escape any underscores (_) by duplicating them
  4. Convert all periods (.) to underscores (_)
from fastlab.decorators import WithEnvConfig

@WithEnvConfig(prefix='FL_')
def load_config():
    return {
      'name': 'fastlab', 
      'version': '0.2.1',
      'extra': {
        'memory_lock': False
      }
    }

conf = load_config()

For example, FL_EXTRA_MEMORY__LOCK=true transform conf['extra']['memory_lock'] as True

Testing

Install this package locally

python setup.py develop

Run test case

python tests/test_logs.py

Download details:

Author: AnoyiX
Source: https://github.com/AnoyiX/fastlab

License: MIT license

#python #fastapi 

FastLab: An extension library for FastAPI framework | Python
Code  Geek

Code Geek

1680055775

Building RESTful APIs with Python | FastAPI Tutorial

In this Python tutorial you will learn about FastAPI, a Web framework for developing RESTful APIs in Python. FastAPI is based on Pydantic and type hints to validate, serialize, and deserialize data, and automatically auto-generate OpenAPI documents. It fully supports asynchronous programming and can run with Uvicorn and Gunicorn

⭐  Table Of Contents ⭐
===========================================
00:00 Intro
02:15 - FastAPI and Uvicorn
04:48 - Up and Running with FastAPI
09:55 - HTTP Methods
13:45 - Async Await 
16:22 - User Model
20:56 - Database
24:48 - HTTP Get Requests
28:51 - HTTP Post Requests
32:13 - Rest Client
38:41 - Swagger Docs and Redoc
44:37 - HTTP Delete Requests
49:38 - HTTP Status Codes
52:13 - Raising Exceptions
55:07 - Exercise
56:20 - Exercise Solution
01:01:24 - Outro

Subscribe: https://www.youtube.com/@amigoscode/featured 

#fastapi  #pythontutorial  

Building RESTful APIs with Python | FastAPI Tutorial

Como criar e usar middleware em FastAPI Python

Neste tutorial do FastAPI Python, aprenderemos como criar e usar middleware no FastAPI Python. O middleware é essencial para qualquer estrutura de desenvolvimento de aplicativos da Web, e o FastAPI do Python não é exceção. No FastAPI, o middleware pode ser usado para adicionar funcionalidade adicional ao ciclo de solicitação e resposta, como autenticação, limitação de taxa ou registro.

Este blog explorará como criar e usar middleware no FastAPI. Abordaremos os seguintes tópicos:

  1. O que é middleware?
  2. Criando middleware no FastAPI
  3. Adicionando middleware ao FastAPI
  4. Testando o middleware

Então vamos começar!

1. O que é middleware?

Middleware é uma camada de software entre o cliente e o servidor em um aplicativo da web. Ele intercepta as solicitações e respostas e pode adicionar, modificar ou excluir as informações à medida que passam. Em outras palavras, middleware é um conjunto de funções executadas antes ou depois que o aplicativo da Web trata a solicitação.

O middleware é útil para adicionar funcionalidade adicional a um aplicativo, como autenticação, registro, limitação de taxa ou modificação de solicitações e respostas. Ele também pode realizar pré-processamento ou pós-processamento dos dados de solicitação/resposta.

2. Criando middleware no FastAPI

A criação de middleware no FastAPI é direta. O middleware é implementado como uma função que recebe dois argumentos: o requeste a call_nextfunção. O requestobjeto contém informações sobre a solicitação recebida, enquanto a call_nextfunção é usada para chamar a próxima função de middleware ou o manipulador de solicitação.

Aqui está um exemplo de uma função de middleware simples que registra o método de solicitação e a URL,

from fastapi import FastAPI
app = FastAPI()
@app.middleware("http")
async def log_request(request, call_next):
    print(f"Received request: {request.method} {request.url}")
    response = await call_next(request)
    return response

Neste exemplo, definimos uma função de middleware log_requestque recebe dois argumentos requeste call_next. O requestobjeto contém informações sobre a solicitação recebida e a call_nextfunção é usada para chamar a próxima função de middleware ou o manipulador de solicitação.

A log_requestfunção registra o método de solicitação de entrada e a URL e, em seguida, chama a próxima função de middleware ou o manipulador de solicitação usando call_next(request).

3. Adicionando middleware ao FastAPI

Para adicionar middleware ao FastAPI, precisamos usar o app.middlewaredecorador. O decorador recebe um argumento, o tipo de middleware, que pode ser "http"para middleware HTTP ou "websocket"para middleware WebSocket.

Aqui está um exemplo de como adicionar a log_requestfunção de middleware ao nosso aplicativo FastAPI,

from fastapi import FastAPI
app = FastAPI()
@app.middleware("http")
async def log_request(request, call_next):
    print(f"Received request: {request.method} {request.url}")
    response = await call_next(request)
    return response

Neste exemplo, adicionamos a log_requestfunção de middleware ao nosso aplicativo FastAPI usando o app.middlewaredecorador. Em seguida, definimos uma rota simples usando o @app.getdecorador.

Quando executamos o aplicativo e fazemos uma solicitação ao endpoint raiz ( http://localhost:8000/), devemos ver a mensagem de log no console,

fonte do artigo em: https://www.c-sharpcorner.com

#python #fastapi 

Como criar e usar middleware em FastAPI Python
Duy  Tien

Duy Tien

1679831820

Cách tạo và sử dụng Middleware trong FastAPI PythonCách tạo và sử dụng

Trong hướng dẫn FastAPI Python này, chúng ta sẽ tìm hiểu về Cách tạo và sử dụng Middleware trong FastAPI Python. Phần mềm trung gian rất cần thiết cho bất kỳ khung phát triển ứng dụng web nào và FastAPI của Python cũng không ngoại lệ. Trong FastAPI, phần mềm trung gian có thể được sử dụng để thêm chức năng bổ sung vào chu trình yêu cầu và phản hồi, chẳng hạn như xác thực, giới hạn tốc độ hoặc ghi nhật ký.

Blog này sẽ khám phá cách tạo và sử dụng phần mềm trung gian trong FastAPI. Chúng tôi sẽ đề cập đến các chủ đề sau:

  1. Phần mềm trung gian là gì?
  2. Tạo phần mềm trung gian trong FastAPI
  3. Thêm phần mềm trung gian vào FastAPI
  4. Kiểm tra phần mềm trung gian

Vậy hãy bắt đầu!

1. Phần mềm trung gian là gì?

Middleware là một lớp phần mềm giữa máy khách và máy chủ trong một ứng dụng web. Nó chặn các yêu cầu và phản hồi và có thể thêm, sửa đổi hoặc xóa thông tin khi nó đi qua. Nói cách khác, phần mềm trung gian là một tập hợp các chức năng được thực thi trước hoặc sau khi ứng dụng web xử lý yêu cầu.

Phần mềm trung gian rất hữu ích để thêm chức năng bổ sung vào ứng dụng, chẳng hạn như xác thực, ghi nhật ký, giới hạn tốc độ hoặc sửa đổi các yêu cầu và phản hồi. Nó cũng có thể thực hiện tiền xử lý hoặc hậu xử lý dữ liệu yêu cầu/phản hồi.

2. Tạo phần mềm trung gian trong FastAPI

Tạo phần mềm trung gian trong FastAPI rất đơn giản. Phần mềm trung gian được triển khai dưới dạng một hàm nhận hai đối số: hàm requestcall_nexthàm. Đối requesttượng chứa thông tin về yêu cầu đến, trong khi call_nextchức năng được sử dụng để gọi chức năng phần mềm trung gian tiếp theo hoặc trình xử lý yêu cầu.

Đây là một ví dụ về chức năng phần mềm trung gian đơn giản ghi lại phương thức yêu cầu và URL,

from fastapi import FastAPI
app = FastAPI()
@app.middleware("http")
async def log_request(request, call_next):
    print(f"Received request: {request.method} {request.url}")
    response = await call_next(request)
    return response

Trong ví dụ này, chúng tôi định nghĩa một hàm phần mềm trung gian log_requestnhận hai đối số requestcall_next. Đối requesttượng chứa thông tin về yêu cầu đến và call_nextchức năng được sử dụng để gọi chức năng phần mềm trung gian tiếp theo hoặc trình xử lý yêu cầu.

Hàm log_requestghi nhật ký phương thức và URL của yêu cầu đến, sau đó gọi hàm phần mềm trung gian tiếp theo hoặc trình xử lý yêu cầu bằng cách sử dụng call_next(request).

3. Thêm phần mềm trung gian vào FastAPI

Để thêm phần mềm trung gian vào FastAPI, chúng ta cần sử dụng app.middlewaretrình trang trí. Trình trang trí nhận một đối số, loại phần mềm trung gian, có thể dành "http"cho phần mềm trung gian HTTP hoặc "websocket"cho phần mềm trung gian WebSocket.

Đây là một ví dụ về việc thêm log_requestchức năng phần mềm trung gian vào ứng dụng FastAPI của chúng tôi,

from fastapi import FastAPI
app = FastAPI()
@app.middleware("http")
async def log_request(request, call_next):
    print(f"Received request: {request.method} {request.url}")
    response = await call_next(request)
    return response

Trong ví dụ này, chúng tôi thêm log_requestchức năng phần mềm trung gian vào ứng dụng FastAPI của mình bằng app.middlewaretrình trang trí. Sau đó, chúng tôi xác định một tuyến đường đơn giản bằng cách sử dụng @app.gettrình trang trí.

Khi chúng tôi chạy ứng dụng và đưa ra yêu cầu tới điểm cuối gốc ( http://localhost:8000/), chúng tôi sẽ thấy thông báo nhật ký trong bảng điều khiển,

nguồn bài viết tại: https://www.c-sharpcorner.com

#python #fastapi 

Cách tạo và sử dụng Middleware trong FastAPI PythonCách tạo và sử dụng