1682736406
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
1680854847
Если длительный процесс является частью рабочего процесса вашего приложения, а не блокирует ответ, вы должны обрабатывать его в фоновом режиме, вне обычного потока запросов/ответов.
Возможно, ваше веб-приложение требует, чтобы пользователи отправляли эскиз (который, вероятно, нужно будет изменить в размере) и подтверждали свой адрес электронной почты при регистрации. Если ваше приложение обработает изображение и отправит электронное письмо с подтверждением непосредственно в обработчике запросов, то конечному пользователю придется без необходимости ждать, пока они оба закончат обработку, прежде чем страница загрузится или обновится. Вместо этого вы захотите передать эти процессы в очередь задач и позволить отдельному рабочему процессу справиться с ними, чтобы вы могли немедленно отправить ответ обратно клиенту. Затем конечный пользователь может выполнять другие действия на стороне клиента, пока происходит обработка. Ваше приложение также может свободно отвечать на запросы других пользователей и клиентов.
Для этого мы проведем вас через процесс установки и настройки Celery и Redis для обработки длительных процессов в приложении FastAPI. Мы также будем использовать Docker и Docker Compose, чтобы связать все вместе. Наконец, мы рассмотрим, как тестировать задачи Celery с помощью модульных и интеграционных тестов.
К концу этого урока вы сможете:
Опять же, чтобы улучшить взаимодействие с пользователем, длительные процессы должны выполняться вне обычного потока HTTP-запросов/ответов, в фоновом процессе.
Примеры:
При создании приложения старайтесь отличать задачи, которые должны выполняться в течение жизненного цикла запроса/ответа, например операции 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?
Наша цель — разработать приложение FastAPI, которое работает вместе с Celery для обработки длительных процессов, выходящих за рамки обычного цикла запроса/ответа.
Клонируйте базовый проект из репозитория 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:
Затем создайте новый файл с именем 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"
}
Также проверьте это в браузере:
Обновите 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/
1680851100
如果一个长时间运行的进程是应用程序工作流的一部分,而不是阻塞响应,您应该在后台处理它,在正常的请求/响应流之外。
也许您的 Web 应用程序要求用户提交缩略图(可能需要重新调整大小)并在注册时确认他们的电子邮件。如果您的应用程序处理图像并直接在请求处理程序中发送确认电子邮件,那么最终用户将不得不在页面加载或更新之前不必要地等待它们完成处理。相反,您需要将这些进程传递给任务队列并让一个单独的工作进程处理它,这样您就可以立即将响应发送回客户端。然后,最终用户可以在处理过程中在客户端做其他事情。您的应用程序也可以自由响应来自其他用户和客户的请求。
为实现这一目标,我们将引导您完成设置和配置Celery和 Redis的过程,以处理 FastAPI 应用程序中长时间运行的进程。我们还将使用 Docker 和 Docker Compose 将所有内容联系在一起。最后,我们将了解如何使用单元测试和集成测试来测试 Celery 任务。
在本教程结束时,您将能够:
同样,为了改善用户体验,长时间运行的进程应该在正常的 HTTP 请求/响应流之外的后台进程中运行。
例子:
在构建应用程序时,请尝试区分应在请求/响应生命周期内运行的任务(如 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?
我们的目标是开发一个与 Celery 一起工作的 FastAPI 应用程序,以处理正常请求/响应周期之外的长时间运行的进程。
从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:
确保测试也通过:
$ 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 、Redis或AWS 简单队列服务 (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:
接下来,在“项目”中创建一个名为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"
}
同样在浏览器中测试一下:
在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/
1680847260
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.
By the end of this tutorial, you will be able to:
Again, to improve user experience, long-running processes should be run outside the normal HTTP request/response flow, in a background process.
Examples:
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
?
BackgroundTasks
runs in the same event loop that serves your app's requests.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.
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:
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
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!
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
:
celery worker
is used to start a Celery worker-A worker.celery
runs the Celery Application (which we'll define shortly)--loglevel=info
sets the logging level to infoNext, 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.
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"
}
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:
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 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:
Kick off a few more tasks to fully test the dashboard:
Try adding a few more workers to see how that affects things:
$ docker-compose up -d --build --scale worker=3
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.
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/
1680816720
在本 FastAPI 教程中,我们将了解 FastAPI 教程:在 Python 中使用 FastAPI 的介绍。API(应用程序编程接口)是现代架构的支柱,因为它们允许应用程序模块化和解耦。这意味着您可以快速轻松地构建应用程序,让您轻松维护和更新它们。
API 在机器学习中也非常重要,因为它们允许不同的应用程序共享数据并协同工作,从而节省时间和精力。在 Python 中构建 API 有许多不同的框架。在 Python 中创建 API 的一些最流行的框架是 Django、Flask 和 FastAPI。本教程深入探讨了称为 FastAPI 的框架之一。
API代表应用程序编程接口。API 是一种软件中介,它允许两个应用程序相互通信。当您在手机上使用某个应用程序时,该应用程序会连接到 Internet 并将数据发送到服务器。然后服务器处理数据并将其发送回您的手机。然后,您手机上的应用程序会解释数据并以可读的方式呈现给您。
API 就像餐厅里的服务员。服务员接受您的订单并将其发送到厨房。然后厨房准备食物并将其送回给服务员。然后服务员把食物端给你。
以同样的方式,API 从应用程序接收请求并将其发送到服务器。然后服务器处理请求并将数据发送回应用程序。然后应用程序解释数据并将其呈现给用户。
图片来源:https://www.techfunnel.com/wp-content/uploads/2021/07/api.png
如果您想了解有关机器学习管道、API 和 MLOps 的更多信息,可以查看我们的机器学习、管道、部署和 MLOps 教程。
FastAPI是一个高性能的 Web 框架,用于基于标准 Python 类型提示使用 Python 3.7+ 构建 API。它可以帮助开发人员快速高效地构建应用程序。FastAPI 建立在 Starlette 网络服务器之上,包括使构建网络应用程序更容易的功能,例如自动数据验证、错误处理和交互式 API 文档。
我们将在本节中单独查看所有这些功能。首先,让我们看看 FastAPI 原始文档中指出的关键特性。
FastAPI 需要 Python 3.7+。它可以使用 pip 安装。您将需要安装 FastAPI 和 ASGI 服务器 `uvicorn`。
``
# install fastapi
pip install fastapi
# install uvicorn
pip install uvicorn
``
让我们直接开始创建一个非常简单的玩具 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。
FastAPI 使用用于定义 API 的OpenAPI标准为您的所有 API 生成一个“模式” 。“模式”是对某物的定义或描述。不是实现它的代码,而只是一个抽象的描述。OpenAPI 架构为 FastAPI 中包含的两个交互式文档系统提供支持。
要查看文档,只需将 `/docs` 添加到 url (` http://127.0.0.1:8000/docs `)。此链接将显示自动交互式 API 文档。
图片作者
单击右上角的“试用”按钮以测试 API。
图片作者
你可以看到响应主体是一个字典。这是 `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。这是它的样子:
图片作者
在构建 API 时,“路径”定义了请求的路由或端点。不过,这里我们还要多做一个选择,那就是“运营”。这里的“操作”一词指的是 HTTP“方法”之一。通过使用这些所谓的“方法”中的一种(或多种),您可以与 HTTP 协议支持的几种路径中的每一种进行通信。通常,您会使用:
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 将检查:
使用类型提示的好处是您可以使用标准 Python (3.6+) 将参数类型、主体等声明为函数参数。你会得到:
所有这三个框架都是 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) |
数据验证 | 不 | 不 | 是的 |
根据techempower运行的测试结果,FastAPI 在整体性能方面优于所有其他框架。
资料来源:https://www.techempower.com/benchmarks/
在本节中,我们将快速构建机器学习管道,然后创建 API 来为模型提供服务。我们将使用低代码 Python 库PyCaret来构建管道并创建 API。PyCaret 与 FastAPI 集成,这使得创建和提供机器学习模型作为 API 变得极其容易。
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')
```
图片由作者输出截断。
设置完成后,我们只需一行代码即可开始模型训练和选择:`compare_models`。通过使用交叉验证,该函数训练和评估模型库中所有估计器的模型性能。此函数的结果是一个评分网格,其中包含从交叉验证获得的平均分数。
```
best = compare_models()
```
图片作者
基于此,性能最好的模型是“Gradient Boosting Regressor”。如果需要,我们可以通过可视化分析模型,并进一步尝试通过超参数调整或模型集成来提高性能,但我们不会在本教程中这样做。
我们将直接构建最佳模型的 API,以使用 FastAPI 在生产中提供预测服务。请记住,PyCaret 与 FastAPI 集成,因此它可以使用 `create_api` 函数从模型自动创建 REST API。
```
create_api (best, 'insurance_prediction_model')
```
现在要运行此 API,请打开命令提示符终端并导航到笔记本所在的文件夹,然后运行以下命令“python insurance_prediction_model.py”。
前往“http://127.0.0.1:8000/docs”,您将看到与本教程前面部分相同的用户界面
图片作者
图片作者
您还可以通过转到“ http://127.0.0.1:8000/redoc ”来查看替代的交互式文档
图片作者
请记住,默认和 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 创建
如果您还想学习如何使用 Flask 在 Python 中从机器学习模型创建简单的 API,
文章原文出处:https: //www.datacamp.com
1680705660
В этом учебном пособии по FastAPI мы узнаем об учебном пособии по FastAPI: введение в использование FastAPI в Python. API (интерфейс прикладного программирования) являются основой современной архитектуры, поскольку они позволяют приложениям быть модульными и независимыми. Это означает, что вы можете создавать приложения быстро и легко, что позволяет легко поддерживать и обновлять их.
API также очень важны для машинного обучения, поскольку они позволяют различным приложениям обмениваться данными и работать вместе, экономя время и силы. Существует множество различных фреймворков для создания API в Python. Одними из самых популярных фреймворков для создания API на Python являются Django, Flask и FastAPI. Этот учебник представляет собой глубокое погружение в один из фреймворков под названием FastAPI.
API означает интерфейс прикладного программирования. API — это программный посредник, который позволяет двум приложениям взаимодействовать друг с другом. Когда вы используете приложение на своем телефоне, оно подключается к Интернету и отправляет данные на сервер. Затем сервер обрабатывает данные и отправляет их обратно на ваш телефон. Затем приложение на вашем телефоне интерпретирует данные и представляет их вам в удобочитаемом виде.
API — это как официант в ресторане. Официант принимает ваш заказ и отправляет его на кухню. Затем кухня готовит еду и отправляет ее обратно официанту. Затем официант приносит вам еду.
Точно так же API принимает запрос от приложения и отправляет его на сервер. Затем сервер обрабатывает запрос и отправляет данные обратно в приложение. Затем приложение интерпретирует данные и представляет их пользователю.
Источник изображения: https://www.techfunnel.com/wp-content/uploads/2021/07/api.png
Если вы хотите узнать больше о конвейерах машинного обучения, API и MLOps, вы можете ознакомиться с нашим учебным пособием по машинному обучению, конвейерам, развертыванию и MLOps .
FastAPI — это высокопроизводительная веб-инфраструктура для создания API-интерфейсов с Python 3.7+ на основе стандартных подсказок типов Python. Это помогает разработчикам создавать приложения быстро и эффективно. FastAPI построен на основе веб-сервера Starlette и включает в себя функции, упрощающие создание веб-приложений, такие как автоматическая проверка данных, обработка ошибок и интерактивная документация по API.
В этом разделе мы рассмотрим все эти функции по отдельности. Во-первых, давайте рассмотрим ключевые функции, указанные в оригинальной документации FastAPI.
FastAPI требует Python 3.7+. Его можно установить с помощью pip. Вам нужно будет установить FastAPI и ASGI-сервер uvicorn.
``
# install fastapi
pip install fastapi
# install uvicorn
pip install uvicorn
``
Давайте непосредственно приступим к созданию очень простого игрушечного 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.
FastAPI создает «схему» со всеми вашими API, используя стандарт OpenAPI для определения API. «Схема» — это определение или описание чего-либо. Не тот код, который его реализует, а просто абстрактное описание. Схема OpenAPI обеспечивает работу двух систем интерактивной документации, включенных в FastAPI.
Чтобы просмотреть документацию, просто добавьте `/docs` к URL-адресу (` http://127.0.0.1:8000/docs` ). Эта ссылка покажет автоматическую интерактивную документацию по API.
Изображение автора
Нажмите кнопку «Попробовать» в правом верхнем углу, чтобы протестировать API.
Изображение автора
Вы можете видеть, что тело ответа представляет собой словарь. Это обратный вызов функции 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`. Вот как это выглядит:
Изображение автора
При создании API «путь» определяет маршрут или конечную точку запроса. Однако здесь мы должны сделать еще один выбор, то есть «Операция». Слово «операция» здесь относится к одному из «методов» HTTP. Используя один (или несколько) из этих так называемых «методов», вы можете взаимодействовать с каждым из нескольких путей, поддерживаемых протоколом HTTP. Как правило, вы должны использовать:
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 проверит:
Преимущество использования подсказок типов заключается в том, что вы один раз объявляете типы параметров, тела и т. д. как параметры функции в стандартном Python (3.6+). Ты получишь:
Все три из этих фреймворков являются веб-фреймворками Python, которые можно использовать для разработки веб-приложений. У каждого из них есть свои сильные и слабые стороны.
Django — это полнофункциональный фреймворк, включающий в себя все необходимое для начала работы, в том числе встроенный ORM и панель администратора. Это может быть немного сложно для новичков, но его исчерпывающая документация облегчает изучение.
Flask — это легкий микрофреймворк, с которым легко начать работу. В нем не так много функций, как в Django, но он идеально подходит для простых проектов.
FastAPI — это новый фреймворк, разработанный для того, чтобы быть быстрым и простым в использовании. Он включает в себя такие функции, как автоматическая проверка данных и документация.
Джанго | Колба | FastAPI | |
Сообщество | Большой. 66 тысяч звезд GitHub | Большой. 61 тысяча звезд на GitHub | Большой. 50 000 звезд на GitHub |
Производительность | Джанго огромен. Это не лучший вариант с точки зрения производительности. | Flask — это микровеб-фреймворк. Он работает лучше, чем Django. | FastAPI — один из самых быстрых веб-фреймворков со встроенной поддержкой асинхронности, которая повышает эффективность фреймворка. |
Асинхронная поддержка | Да, с ограниченной задержкой. | Нет. Нужен Асинкио | FastAPI обеспечивает встроенную поддержку асинхронности. |
Простота использования | Django огромен и, следовательно, немного сложен в освоении. | Flask прост в освоении и довольно прост в использовании. | FastAPI — самый простой из всех трех. |
Интерактивная документация | Не интерактивный | Нет | Да (OpenAI, редок) |
Проверка данных | Нет | Нет | Да |
По результатам тестов, проведенных techempower , FastAPI превосходит все остальные фреймворки по своей общей производительности.
Источник: https://www.techempower.com/benchmarks/
В этом разделе мы быстро создадим конвейер машинного обучения, а затем создадим 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')
```
Изображение автора. Выходные данные усечены.
После завершения настройки мы можем начать обучение и выбор модели с помощью всего одной строки кода: `compare_models`. С помощью перекрестной проверки эта функция обучает и оценивает производительность модели всех средств оценки в библиотеке моделей. Результатом этой функции является сетка оценок, содержащая средние оценки, полученные в результате перекрестной проверки.
```
best = compare_models()
```
Изображение автора
Исходя из этого, наиболее эффективной моделью является «Gradient Boosting Regressor». Если мы хотим, мы можем проанализировать модель с помощью визуализации и дополнительно попытаться улучшить производительность с помощью настройки гиперпараметров или объединения моделей, но мы не будем этого делать в этом руководстве.
Мы приступим непосредственно к созданию API лучшей модели для обслуживания прогнозов в производственной среде с использованием FastAPI. Помните, что PyCaret имеет интеграцию с FastAPI, поэтому он может автоматически создавать REST API из модели с помощью функции create_api.
```
create_api (best, 'insurance_prediction_model')
```
Теперь, чтобы запустить этот API, откройте терминал командной строки, перейдите в папку, в которой находится ваш ноутбук, и выполните следующую команду `python Insurance_prediction_model.py`.
Перейдите по адресу `http://127.0.0.1:8000/docs`, и вы увидите тот же пользовательский интерфейс, который вы видели ранее в этом руководстве.
Изображение автора
Изображение автора
Вы также можете просмотреть альтернативную интерактивную документацию, перейдя по адресу ` http://127.0.0.1:8000/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-history.com
Если вы также хотите узнать, как создать простой API из модели машинного обучения в Python с помощью Flask,
Оригинальный источник статьи: https://www.datacamp.com
1680699240
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.
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.
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 .
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.
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
``
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:
Vá até o link em seu navegador e, se vir uma página que mostra "Hello World", a API está funcionando.
Imagem do autor
Parabéns por criar sua primeira API.
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.
Imagem do autor
Clique no botão `Try it out` no canto superior direito para testar a API.
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:
Imagem do autor
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:
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á:
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:
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.
Django | Frasco | FastAPI | |
Comunidade | Grande. 66 mil estrelas do GitHub | Grande. 61 mil estrelas do GitHub | Grande. 50 mil estrelas do GitHub |
Desempenho | Django é 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íncrono | Sim, com latência limitada. | Não. Necessita Assincio | FastAPI fornece suporte assíncrono nativo. |
Fácil de usar | Django é 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 interativa | Não interativo | Não | Sim (OpenAI, Redoc) |
Verificação de dados | Não | Não | Sim |
De acordo com os resultados dos testes executados pela techempower , o FastAPI é superior a todos os outros frameworks em termos de desempenho geral.
Fonte: https://www.techempower.com/benchmarks/
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.
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’)
```
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')
```
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()
```
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')
```
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`.
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
Image by Author
Image by Author
You can also see alternative interactive documentation by going to `http://127.0.0.1:8000/redoc’
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)
```
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
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
1680680520
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à 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.
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à 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.
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
``
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:
Đ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.
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.
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.
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.
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ư:
Hình ảnh của tác giả
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:
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:
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:
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.
Django | Bình giữ nhiệt | API 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ất | Django 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ụng | Django 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ác | Không tương tác | KHÔNG | Có (OpenAI, Redoc) |
Xác minh dữ liệu | KHÔNG | KHÔNG | Đúng |
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ó.
Nguồn: https://www.techempower.com/benchmarks/
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 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’)
```
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')
```
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()
```
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')
```
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`.
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
Hình ảnh của tác giả
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 '
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)
```
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
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
1680501900
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.
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.
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.
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.
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
``
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:
Head over to the link in your browser, and if you see a page that shows `Hello World,` the API is up and running.
Image by Author
Congratulations on building your first API.
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.
Image by Author
Click on `Try it out` button in the top right corner to test the API.
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:
Image by Author
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:
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:
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:
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.
Django | Flask | FastAPI | |
Community | Big. 66K GitHub stars | Big. 61K GitHub stars | Big. 50K GitHub stars |
Performance | Django 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 support | Yes, with limited latency. | No. Needs Asyncio | FastAPI provides native async support. |
Ease of use | Django 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 Documentation | Not interactive | No | Yes (OpenAI, Redoc) |
Data Verification | No | No | Yes |
According to the results of tests run by techempower, FastAPI is superior to all other frameworks in terms of its overall performance.
Source: https://www.techempower.com/benchmarks/
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 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’)
```
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')
```
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()
```
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')
```
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`.
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
Image by Author
Image by Author
You can also see alternative interactive documentation by going to `http://127.0.0.1:8000/redoc’
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)
```
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
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
1680350700
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"}
-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!👍
Author: Abbhiishek
Source: https://github.com/Abbhiishek/Sociome
License: MIT license
1680343260
fastapi-event is event dispatcher for FastAPI framework.
pip3 install fastapi-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
.
from pydantic import BaseModel
class TestEventParameter(BaseModel):
id: str
pw: str
In case of need parameter, you have to inherit BaseModel
and set fields.
from fastapi import FastAPI
from fastapi_event import EventHandlerMiddleware
app = FastAPI()
app.add_middleware(EventHandlerMiddleware)
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.
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.
Author: teamhide
Source: https://github.com/teamhide/fastapi-event
License: Apache-2.0 license
1680339480
An extension library for FastAPI framework
use pip
to install the package:
pip install fastlab
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
Common Models
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"
}
}
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))
from fastlab.utils import TimeUtils
# Print now timestamp: 1639732030521
print(TimeUtils.timestamp())
API for health check, endpoint /health
.
from fastapi import FastAPI
from fastlab.routers import HealthRouter
app = FastAPI()
app.include_router(HealthRouter)
Replace the configuration with system environment variables. Follows:
prefix
setting_
) by duplicating them_
)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
Install this package locally
python setup.py develop
Run test case
python tests/test_logs.py
Author: AnoyiX
Source: https://github.com/AnoyiX/fastlab
License: MIT license
1680055775
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
1679836200
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:
Então vamos começar!
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.
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).
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
1679831820
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:
Vậy hãy bắt đầu!
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.
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 requestvà call_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ố requestvà call_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).
Để 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