FastAPI: A Modern, High Performance, Web Framework

FastAPI framework, high performance, easy to learn, fast to code, ready for production


Documentation: https://fastapi.tiangolo.com

Source Code: https://github.com/tiangolo/fastapi


FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+ based on standard Python type hints.

The key features are:

Fast: Very high performance, on par with NodeJS and Go (thanks to Starlette and Pydantic). One of the fastest Python frameworks available.

Fast to code: Increase the speed to develop features by about 200% to 300%. *

Fewer bugs: Reduce about 40% of human (developer) induced errors. *

Intuitive: Great editor support. Completion everywhere. Less time debugging.

Easy: Designed to be easy to use and learn. Less time reading docs.

Short: Minimize code duplication. Multiple features from each parameter declaration. Fewer bugs.

Robust: Get production-ready code. With automatic interactive documentation.

Standards-based: Based on (and fully compatible with) the open standards for APIs: OpenAPI (previously known as Swagger) and JSON Schema.

* estimation based on tests on an internal development team, building production applications.

Sponsors

Other sponsors

Opinions

"[...] I'm using FastAPI a ton these days. [...] I'm actually planning to use it for all of my team's ML services at Microsoft. Some of them are getting integrated into the core Windows product and some Office products."

Kabir Khan - Microsoft (ref)


"We adopted the FastAPI library to spawn a REST server that can be queried to obtain predictions. [for Ludwig]"

Piero Molino, Yaroslav Dudin, and Sai Sumanth Miryala - Uber (ref)


"Netflix is pleased to announce the open-source release of our crisis management orchestration framework: Dispatch! [built with FastAPI]"

Kevin Glisson, Marc Vilanova, Forest Monsen - Netflix (ref)


"I’m over the moon excited about FastAPI. It’s so fun!"

Brian Okken - Python Bytes podcast host (ref)


"Honestly, what you've built looks super solid and polished. In many ways, it's what I wanted Hug to be - it's really inspiring to see someone build that."

Timothy Crosley - Hug creator (ref)


"If you're looking to learn one modern framework for building REST APIs, check out FastAPI [...] It's fast, easy to use and easy to learn [...]"

"We've switched over to FastAPI for our APIs [...] I think you'll like it [...]"

Ines Montani - Matthew Honnibal - Explosion AI founders - spaCy creators (ref) - (ref)


Typer, the FastAPI of CLIs

If you are building a CLI app to be used in the terminal instead of a web API, check out Typer.

Typer is FastAPI's little sibling. And it's intended to be the FastAPI of CLIs. ⌨️ 🚀

Requirements

Python 3.6+

FastAPI stands on the shoulders of giants:

Installation

$ pip install fastapi

---> 100%

You will also need an ASGI server, for production such as Uvicorn or Hypercorn.

$ pip install "uvicorn[standard]"

---> 100%

Example

Create it

  • Create a file main.py with:
from typing import Optional

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: Optional[str] = None):
    return {"item_id": item_id, "q": q}

Or use async def...

If your code uses async / await, use async def:

from typing import Optional

from fastapi import FastAPI

app = FastAPI()


@app.get("/")
async def read_root():
    return {"Hello": "World"}


@app.get("/items/{item_id}")
async def read_item(item_id: int, q: Optional[str] = None):
    return {"item_id": item_id, "q": q}

Note:

If you don't know, check the "In a hurry?" section about async and await in the docs.

Run it

Run the server with:

$ uvicorn main:app --reload

INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO:     Started reloader process [28720]
INFO:     Started server process [28722]
INFO:     Waiting for application startup.
INFO:     Application startup complete.

About the command uvicorn main:app --reload...

The command uvicorn main:app refers to:

  • main: the file main.py (the Python "module").
  • app: the object created inside of main.py with the line app = FastAPI().
  • --reload: make the server restart after code changes. Only do this for development.

Check it

Open your browser at http://127.0.0.1:8000/items/5?q=somequery.

You will see the JSON response as:

{"item_id": 5, "q": "somequery"}

You already created an API that:

  • Receives HTTP requests in the paths / and /items/{item_id}.
  • Both paths take GET operations (also known as HTTP methods).
  • The path /items/{item_id} has a path parameter item_id that should be an int.
  • The path /items/{item_id} has an optional str query parameter q.

Interactive API docs

Now go to http://127.0.0.1:8000/docs.

You will see the automatic interactive API documentation (provided by Swagger UI):

Swagger UI

Alternative API docs

And now, go to http://127.0.0.1:8000/redoc.

You will see the alternative automatic documentation (provided by ReDoc):

ReDoc

Example upgrade

Now modify the file main.py to receive a body from a PUT request.

Declare the body using standard Python types, thanks to Pydantic.

from typing import Optional

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()


class Item(BaseModel):
    name: str
    price: float
    is_offer: Optional[bool] = None


@app.get("/")
def read_root():
    return {"Hello": "World"}


@app.get("/items/{item_id}")
def read_item(item_id: int, q: Optional[str] = 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}

The server should reload automatically (because you added --reload to the uvicorn command above).

Interactive API docs upgrade

Now go to http://127.0.0.1:8000/docs.

  • The interactive API documentation will be automatically updated, including the new body:

Swagger UI

  • Click on the button "Try it out", it allows you to fill the parameters and directly interact with the API:

Swagger UI interaction

  • Then click on the "Execute" button, the user interface will communicate with your API, send the parameters, get the results and show them on the screen:

Swagger UI interaction

Alternative API docs upgrade

And now, go to http://127.0.0.1:8000/redoc.

  • The alternative documentation will also reflect the new query parameter and body:

ReDoc

Recap

In summary, you declare once the types of parameters, body, etc. as function parameters.

You do that with standard modern Python types.

You don't have to learn a new syntax, the methods or classes of a specific library, etc.

Just standard Python 3.6+.

For example, for an int:

item_id: int

or for a more complex Item model:

item: Item

...and with that single declaration you get:

  • Editor support, including:
    • Completion.
    • Type checks.
  • Validation of data:
    • Automatic and clear errors when the data is invalid.
    • Validation even for deeply nested JSON objects.
  • Conversion of input data: coming from the network to Python data and types. Reading from:
    • JSON.
    • Path parameters.
    • Query parameters.
    • Cookies.
    • Headers.
    • Forms.
    • Files.
  • Conversion of output data: converting from Python data and types to network data (as JSON):
    • Convert Python types (str, int, float, bool, list, etc).
    • datetime objects.
    • UUID objects.
    • Database models.
    • ...and many more.
  • Automatic interactive API documentation, including 2 alternative user interfaces:
    • Swagger UI.
    • ReDoc.

Coming back to the previous code example, FastAPI will:

  • Validate that there is an item_id in the path for GET and PUT requests.
  • Validate that the item_id is of type int for GET and PUT requests.
    • If it is not, the client will see a useful, clear error.
  • Check if there is an optional query parameter named q (as in http://127.0.0.1:8000/items/foo?q=somequery) for GET requests.
    • As the q parameter is declared with = None, it is optional.
    • Without the None it would be required (as is the body in the case with PUT).
  • For PUT requests to /items/{item_id}, Read the body as JSON:
    • Check that it has a required attribute name that should be a str.
    • Check that it has a required attribute price that has to be a float.
    • Check that it has an optional attribute is_offer, that should be a bool, if present.
    • All this would also work for deeply nested JSON objects.
  • Convert from and to JSON automatically.
  • Document everything with OpenAPI, that can be used by:
    • Interactive documentation systems.
    • Automatic client code generation systems, for many languages.
  • Provide 2 interactive documentation web interfaces directly.

We just scratched the surface, but you already get the idea of how it all works.

Try changing the line with:

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

...from:

        ... "item_name": item.name ...

...to:

        ... "item_price": item.price ...

...and see how your editor will auto-complete the attributes and know their types:

editor support

For a more complete example including more features, see the Tutorial - User Guide.

Spoiler alert: the tutorial - user guide includes:

  • Declaration of parameters from other different places as: headers, cookies, form fields and files.
  • How to set validation constraints as maximum_length or regex.
  • A very powerful and easy to use Dependency Injection system.
  • Security and authentication, including support for OAuth2 with JWT tokens and HTTP Basic auth.
  • More advanced (but equally easy) techniques for declaring deeply nested JSON models (thanks to Pydantic).
  • GraphQL integration with Strawberry and other libraries.
  • Many extra features (thanks to Starlette) as:
    • WebSockets
    • extremely easy tests based on requests and pytest
    • CORS
    • Cookie Sessions
    • ...and more.

Performance

Independent TechEmpower benchmarks show FastAPI applications running under Uvicorn as one of the fastest Python frameworks available, only below Starlette and Uvicorn themselves (used internally by FastAPI). (*)

To understand more about it, see the section Benchmarks.

Optional Dependencies

Used by Pydantic:

Used by Starlette:

  • requests - Required if you want to use the TestClient.
  • jinja2 - Required if you want to use the default template configuration.
  • python-multipart - Required if you want to support form "parsing", with request.form().
  • itsdangerous - Required for SessionMiddleware support.
  • pyyaml - Required for Starlette's SchemaGenerator support (you probably don't need it with FastAPI).
  • ujson - Required if you want to use UJSONResponse.

Used by FastAPI / Starlette:

  • uvicorn - for the server that loads and serves your application.
  • orjson - Required if you want to use ORJSONResponse.

You can install all of these with pip install "fastapi[all]".

License

This project is licensed under the terms of the MIT license.

Author: tiangolo
Source Code: https://github.com/tiangolo/fastapi
License: MIT License

#python #fastapi 

FastAPI: A Modern, High Performance, Web Framework
Wasswa  Meagan

Wasswa Meagan

1652457600

API Uses FastAPI and PostgreSQL to Share Recipes

ChefAPI

API using FastAPI and PostgreSQL to create and share or keeping track of awesome food recipes. Our API have aslo a Crud System Using JWT and Oauth2 to Create a Complete API that Can Be Used with a High Quality Frontend Project. ⛏

Getting Started

  • To start using ChefAPI You need some experience in Cuisine maybe how to create a Moroccan CousCous or Tajine.

Prerequisites

  • Python 3.8.6 or higher
  • PostgreSQL
  • FastAPI
  • Docker

Project setup

# clone the repo
$ git clone https://github.com/GDGSNF/ChefAPI

# move to the project folder
$ cd ChefAPI

Creating virtual environment

  • Install pipenv a global python project pip install pipenv
  • Create a virtual environment for this project
# creating pipenv environment for python 3
$ pipenv --three

# activating the pipenv environment
$ pipenv shell

# if you have multiple python 3 versions installed then
$ pipenv install -d --python 3.8

# install all dependencies (include -d for installing dev dependencies)
$ pipenv install -d

Configured Enviromment

Database

  • Using SQLAlchemy to Connect to our PostgreSQL Database
  • Containerization The Database.
  • Drop your PostgreSQL Configuration at the .env.sample and Don't Forget to change the Name to .env
# example of Configuration for the .env file

POSTGRES_SERVER = localhost
POSTGRES_USER = root
POSTGRES_PASSWORD = password
POSTGRES_DB = ChefAPI

Running the Application

  • To run the Main we need to use uvicorn a lightning-fast ASGI server implementation, using uvloop and httptools.
# Running the application using uvicorn
$ uvicorn main:app

# To run the Application under a reload enviromment use -- reload
$ uvicorn main:app --reload

Running the Docker Container

  • We have the Dockerfile created in above section. Now, we will use the Dockerfile to create the image of the FastAPI app and then start the FastAPI app container.
$ docker build
  • list all the docker images and you can also see the image chefapi:latest in the list.
$ docker images
  • run the application at port 5000. The various options used are:
  • -p: publish the container's port to the host port.
  • -d: run the container in the background.
  • -i: run the container in interactive mode.
  • -t: to allocate pseudo-TTY.
  • --name: name of the container
$ docker container run -p 5000:5000 -dit --name ChefAPI chefapi:latest
  • Check the status of the docker container
$ docker container ps

Preconfigured Packages

Includes preconfigured packages to kick start ChefAPI by just setting appropriate configuration.

PackageUsage
uvicorna lightning-fast ASGI server implementation, using uvloop and httptools.
Python-Josea JavaScript Object Signing and Encryption implementation in Python.
SQLAlchemyis the Python SQL toolkit and Object Relational Mapper that gives application developers the full power and flexibility of SQL.
starlettea lightweight ASGI framework/toolkit, which is ideal for building high performance asyncio services.
passliba password hashing library for Python 2 & 3, which provides cross-platform implementations of over 30 password hashing algorithms
bcryptGood password hashing for your software and your servers.
python-multipartstreaming multipart parser for Python.

yapf packages for linting and formatting

Contributing

  • Join the ChefAPI Creator and Contribute to the Project if you have any enhancement or add-ons to create a good and Secure Project, Help any User to Use it in a good and simple way.

Author: yezz123
Source Code: https://github.com/yezz123/ChefAPI
License: MIT license

#postgresql #fastapi 

API Uses FastAPI and PostgreSQL to Share Recipes

Repository for Project Insight: NLP as a Service

Project Insight

NLP as a Service

Introduction

Project Insight is designed to create NLP as a service with code base for both front end GUI (streamlit) and backend server (FastApi) the usage of transformers models on various downstream NLP task.

The downstream NLP tasks covered:

News Classification

Entity Recognition

Sentiment Analysis

Summarization

Information Extraction To Do

The user can select different models from the drop down to run the inference.

The users can also directly use the backend fastapi server to have a command line inference.

 

Features of the solution

  • Python Code Base: Built using Fastapi and Streamlit making the complete code base in Python.
  • Expandable: The backend is desinged in a way that it can be expanded with more Transformer based models and it will be available in the front end app automatically.
  • Micro-Services: The backend is designed with a microservices architecture, with dockerfile for each service and leveraging on Nginx as a reverse proxy to each independently running service.
    • This makes it easy to update, manitain, start, stop individual NLP services.

 

Installation

  • Clone the Repo.
  • Run the Docker Compose to spin up the Fastapi based backend service.
  • Run the Streamlit app with the streamlit run command.

 

Setup and Documentation

Download the models

  • Download the models from here
  • Save them in the specific model folders inside the src_fastapi folder.

Running the backend service.

  • Go to the src_fastapi folder
  • Run the Docker Compose comnand

Running the frontend app.

  • Go to the src_streamlit folder

Author: abhimishra91
Source Code: https://github.com/abhimishra91/insight
License: GPL-3.0 license

#streamlit #fastapi 

Repository for Project Insight: NLP as a Service

Flake8 Plugin That Checks FastAPI Code Against Opinionated Style Rules

flake8-fastapi

A flake8 plugin that helps you avoid simple FastAPI mistakes.

Installation

First, install the package:

pip install flake8-fastapi

Then, check if the plugin is installed using flake8:

$ flake8 --version
3.9.2 (flake8-fastapi: 0.2.0, mccabe: 0.6.1, pycodestyle: 2.7.0, pyflakes: 2.3.1) CPython 3.8.11 on Linux

Rules

CF001 - Route Decorator Error

Developers that were used to flask can be persuaded or want to use the same pattern in FastAPI:

from fastapi import FastAPI

app = FastAPI()


@app.route("/", methods=["GET"])
def home():
    return "Hello world!"

But on FastAPI, we have a simpler way to define this (and is the most known way to create endpoints):

from fastapi import FastAPI

app = FastAPI()


@app.get("/")
def home():
    return "Hello world!"

CF002 - Router Prefix Error

On old FastAPI versions, we were able to add a prefix only on the include_router method:

from fastapi import APIRouter, FastAPI

router = APIRouter()


@router.get("/")
def home():
    ...


app = FastAPI()
app.include_router(router, prefix="/prefix")

Now, it's possible to add in the Router initialization:

from fastapi import APIRouter, FastAPI

router = APIRouter(prefix="/prefix")


@router.get("/")
def home():
    ...


app = FastAPI()
app.include_router(router)

CF004 - Generic Exception Handler

FastAPI doesn't allow us to handle the base Exception with exception_handler decorator. It's due to Starlette implementation, but well, FastAPI inherits the issue.

To be more precise, you'll be able to receive the response, but as soon as you check the server logs, you'll see an unexpected trace log.

To exemplify, you can't do:

from fastapi import FastAPI, Request
from starlette.responses import JSONResponse

app = FastAPI()


@app.exception_handler(Exception)
async def generic_exception_handler(request: Request, exc: Exception):
    return JSONResponse(status_code=200, content="It doesn't work!")


@app.get("/")
async def home():
    raise Exception()

But you can create a new exception, inheriting from Exception, or use HTTPException:

from fastapi import FastAPI, Request
from starlette.responses import JSONResponse

app = FastAPI()


class NewException(Exception):
    ...


@app.exception_handler(NewException)
async def new_exception_handler(request: Request, exc: NewException):
    return JSONResponse(status_code=200, content="It works!")


@app.get("/")
async def home():
    raise NewException()

CF008 - CORSMiddleware Order

There's a tricky issue about CORSMiddleware that people are usually unaware. Which is that this middleware should be the last one on the middleware stack. You can read more about it here.

Let's see an example of what doesn't work:

from fastapi import FastAPI

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=['*'],
    allow_credentials=True,
    allow_methods=['*'],
    allow_headers=['*']
)
app.add_middleware(GZipMiddleware)

As you see, the last middleware added is not CORSMiddleware, so it will not work as expected. On the other hand, if you change the order, it will:

from fastapi import FastAPI

app = FastAPI()

app.add_middleware(GZipMiddleware)
app.add_middleware(
    CORSMiddleware,
    allow_origins=['*'],
    allow_credentials=True,
    allow_methods=['*'],
    allow_headers=['*']
)

CF009 - Undocumented HTTPException

Currently, there's no automatic solution to document the HTTPExceptions, besides the experimental package fastapi-responses.

For that reason, it's easy to forget the documentation, and have a lot of undocumented endpoints. Let's see an example:

from fastapi import FastAPI, HTTPException

app = FastAPI()


@app.get("/")
def home():
    raise HTTPException(status_code=400, detail="Bad Request")

The above endpoint doesn't have a responses field, even if it's clear that the response will have a 400 status code.

CF011 - No Content Response

Currently, if you try to send a response with no content (204), FastAPI will send a 204 status with a non-empty body. It will send a body content-length being 4 bytes.

You can verify this statement running the following code:

# main.py
from fastapi import FastAPI

app = FastAPI()


@app.get("/", status_code=204)
def home():
    ...

Now feel free to run with your favorite server implementation:

uvicorn main:app

Then use curl or any other tool to send a request:

$ curl localhost:8000
*   Trying 127.0.0.1:8000...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8000 (#0)
> GET / HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 204 No Content
< date: Sat, 24 Jul 2021 19:21:24 GMT
< server: uvicorn
< content-length: 4
< content-type: application/json
<
* Connection #0 to host localhost left intact

This goes against the RFC, which specifies that a 204 response should have no body.

Author: Kludex
Source Code: https://github.com/Kludex/flake8-fastapi
License: MIT license

#python #fastapi 

Flake8 Plugin That Checks FastAPI Code Against Opinionated Style Rules

Simple Web Application Serving Pytorch Model using Streamlit/FastAPI

streamlit-fastapi-model-serving

Simple example of usage of streamlit and FastAPI for ML model serving described on this blogpost and PyConES 2020 video.

When developing simple APIs that serve machine learning models, it can be useful to have both a backend (with API documentation) for other applications to call and a frontend for users to experiment with the functionality.

In this example, we serve an image semantic segmentation model using FastAPI for the backend service and streamlit for the frontend service. docker-compose orchestrates the two services and allows communication between them.

To run the example in a machine running Docker and docker-compose, run:

docker-compose build
docker-compose up

To visit the FastAPI documentation of the resulting service, visit http://localhost:8000 with a web browser.
To visit the streamlit UI, visit http://localhost:8501.

Logs can be inspected via:

docker-compose logs

Deployment

To deploy the app, one option is deployment on Heroku (with Dockhero). To do so:

  • rename docker-compose.yml to dockhero-compose.yml
  • create an app (we refer to its name as <my-app>) on a Heroku account
  • install locally the Heroku CLI, and enable the Dockhero plugin with heroku plugins:install dockhero
  • add to the app the DockHero add-on (and with a plan allowing enough RAM to run the model!)
  • in a command line enter heroku dh:compose up -d --app <my-app> to deploy the app
  • to find the address of the app on the web, enter heroku dh:open --app <my-app>
  • to visualize the api, visit the address adding port 8000/docs, e.g. http://dockhero-<named-assigned-to-my-app>-12345.dockhero.io:8000/docs(not https)
  • visit the address adding :8501 to visit the streamlit interface
  • logs are accessible via heroku logs -p dockhero --app <my-app>

Debugging

To modify and debug the app, development in containers can be useful (and kind of fun!).


Author: davidefiocco
Source Code: https://github.com/davidefiocco/streamlit-fastapi-model-serving
License: MIT license

#streamlit #fastapi #pytorch 

Simple Web Application Serving Pytorch Model using Streamlit/FastAPI
伊藤  直子

伊藤 直子

1651878300

FastAPIでサーバー送信イベント(SSE)を使用する方法

サーバー送信イベント(SSE)は、ページをリロードせずにブラウザーにデータを送信する方法です。これにより、ストリーミングデータを使用して、さまざまなシナリオで使用できるリアルタイムアプリケーションを構築できます。

FastAPIは、APIの構築を容易にするPythonフレームワークです。

このチュートリアルでは、FastAPIを使用して、毎秒メッセージを送信する単純なSSEサーバーを作成します。

前提条件

このチュートリアルに従うには、Pythonとpipをマシンにインストールする必要があります。

https://www.python.org/downloads/

FastAPIのインストール

FastAPIとそのすべての依存関係をインストールするには、次のコマンドを使用できます。

pip install "fastapi[all]"

これには、uvicornサーバーの実行に使用されるサーバーも含まれます。

インストールsse-starlette

FastAPIをインストールしたら、sse-starlette拡張機能をインストールして、FastAPIプロジェクトにSSEのサポートを追加できます。

pip install sse-starlette

asyncioプロジェクトに追加しましょう:

pip install asyncio

単純なHelloWorldエンドポイントの作成

FastAPIをインストールしたら、簡単なhelloworldエンドポイントを作成して開始できます。

という新しいファイルを作成しmain.py、次のコードを追加します。

import asyncio
import uvicorn
from fastapi import FastAPI, Request

app = FastAPI()


@app.get("/")
async def root():
    return {"message": "Hello World"}

uvicornサーバーの実行

サーバーを実行するには、次のコマンドを使用できます。

uvicorn main:app --reload

これにより、サーバーがポートで実行されます8000。コードに変更を加えると、--reloadフラグによってサーバーが自動的に再ロードされるため、変更を加えるたびにサーバーを再起動する必要はありません。

ブラウザでサーバーにアクセスすると、次の出力が表示されます。

{
    "message": "Hello World"
}

/docsFastAPIは、APIドキュメントを表示するエンドポイントを自動的に生成します。にアクセス/docsすると、次のように表示されます。

FastAPIドキュメントエンドポイント

FastAPIプロジェクトにSSEサポートを追加する

次に、main.pyファイルを拡張してSSEサポートを追加しましょう。main.pyこれを行うには、ファイルに次の行を追加して、プロジェクトにSSEサポートを追加します。

from sse_starlette.sse import EventSourceResponse

次に、EventSourceResponseクラスを使用して、SSEイベントを送信する応答を作成できます。1秒ごとにイベントを送信する新しいエンドポイントを作成しましょう。

STREAM_DELAY = 1  # second
RETRY_TIMEOUT = 15000  # milisecond

@app.get('/stream')
async def message_stream(request: Request):
    def new_messages():
        # Add logic here to check for new messages
        yield 'Hello World'
    async def event_generator():
        while True:
            # If client closes connection, stop sending events
            if await request.is_disconnected():
                break

            # Checks for new messages and return them to client if any
            if new_messages():
                yield {
                        "event": "new_message",
                        "id": "message_id",
                        "retry": RETRY_TIMEOUT,
                        "data": "message_content"
                }

            await asyncio.sleep(STREAM_DELAY)

    return EventSourceResponse(event_generator())

これで、ブラウザでエンドポイントにアクセスする/streamと、ページをリロードしなくても、毎秒送信されるイベントが表示されます。

ストリーミングデータとマテリアライズを備えたFastAPI

ストリーミングデータの詳細については、マテリアライズでFastAPIを使用する方法に関するこのチュートリアルをご覧ください。

リアルタイムデータ処理のためにマテリアライズでFastAPIを使用する方法

チュートリアルには、すべてがどのように機能するかを理解するために実行できるデモプロジェクトも含まれています。

プロジェクトの簡単な図は次のとおりです。

マテリアライズを使用したFastAPI

マテリアライズとは何ですか?

マテリアライズは、Kafka、PostgreSQL、S3バケットなどのさまざまなソースからのデータを取得するストリーミングデータベースであり、ユーザーはそのデータを集約/マテリアライズするビューを記述し、非常に低いレイテンシで純粋なSQLを使用してそれらのビューをクエリできます。

Materializeを使用したデータのストリーミング

デモプロジェクトでは、[TAIL](https://materialize.com/docs/sql/tail/#conceptual-framework)ステートメントを使用しています。TAILソース、テーブル、またはビューから更新を発生時にストリーミングします。これにより、更新中のデータをクエリでき、SSEの例に最適です。

データのストリーミング/streamに使用するエンドポイントのコードは次のとおりです。TAIL

@app.get('/stream')
async def message_stream(request: Request):
    def new_messages():
        # Check if data in table
        results = engine.execute('SELECT count(*) FROM sensors_view_1s')
        if results.fetchone()[0] == 0:
            return None
        else:
            return True

    async def event_generator():
        while True:
            # If client was closed the connection
            if await request.is_disconnected():
                break

            # Checks for new messages and return them to client if any
            if new_messages():
                connection = engine.raw_connection()
                with connection.cursor() as cur:
                    cur.execute("DECLARE c CURSOR FOR TAIL sensors_view_1s")
                    cur.execute("FETCH ALL c")
                    for row in cur:
                        yield row

            await asyncio.sleep(MESSAGE_STREAM_DELAY)

    return EventSourceResponse(event_generator())

ご覧のとおりnew_message、ビューに新しいメッセージがあるかどうかを確認するために関数を拡張しましたsensors_view_1s。新しいメッセージがない場合、私たちは戻っNoneてきて、EventSourceResponseイベントを送信しません。新しいメッセージがある場合は、戻っTrueEventSourceResponse新しいメッセージを送信します。

次に、event_generatorasync関数でTAILFETCH ALLステートメントとともに使用して、sensors_view_1sビュー内のすべてのメッセージを取得します。このDECLARE CURSORステートメントを使用して、更新時にデータをストリーミングするカーソルを作成しています。

結論

FastAPIの詳細については、 FastAPIのドキュメントを確認してください。

マテリアライズでFastAPIを使用する方法の詳細については、このチュートリアルを確認してください。 

ソース:https ://hackernoon.com/how-to-use-server-sent-events-sse-with-fastapi

#fastapi #sse

FastAPIでサーバー送信イベント(SSE)を使用する方法

Cómo Usar Eventos Enviados Por El Servidor (SSE) Con FastAPI

Los eventos enviados por el servidor (SSE) son una forma de enviar datos al navegador sin recargar la página. Esto le permite usar transmisión de datos y crear aplicaciones en tiempo real que se pueden usar en una variedad de escenarios.

FastAPI es un marco de Python que facilita la creación de API.

En este tutorial, usaremos FastAPI para crear un servidor SSE simple que enviará un mensaje cada segundo.

requisitos previos

Para seguir este tutorial, deberá tener Python y pip instalados en su máquina:

https://www.python.org/descargas/

Instalación de FastAPI

Para instalar FastAPI y todas sus dependencias, puede usar el siguiente comando:

pip install "fastapi[all]"

Esto también incluirá el uvicornservidor, que se utiliza para ejecutar el servidor.

Instalandosse-starlette

Una vez que haya instalado FastAPI, puede instalar la sse-starletteextensión para agregar soporte para SSE a su proyecto FastAPI:

pip install sse-starlette

Agreguemos también asyncioa nuestro proyecto:

pip install asyncio

Creación de un punto final simple de hola mundo

Una vez que haya instalado FastAPI, puede crear un punto final simple de hola mundo para comenzar.

Cree un nuevo archivo llamado main.pyy agregue el siguiente código:

import asyncio
import uvicorn
from fastapi import FastAPI, Request

app = FastAPI()


@app.get("/")
async def root():
    return {"message": "Hello World"}

Ejecutando el uvicornservidor

Para ejecutar el servidor, puede usar el siguiente comando:

uvicorn main:app --reload

Esto ejecutará el servidor en el puerto 8000. La --reloadbandera recargará automáticamente el servidor cuando realice cambios en el código para que no tenga que reiniciar el servidor cada vez que realice un cambio.

Visite el servidor en su navegador y debería ver el siguiente resultado:

{
    "message": "Hello World"
}

FastAPI generará automáticamente un /docspunto final que le mostrará la documentación de la API. Si fuera a visitar /docs, vería lo siguiente:

Extremo de documentos de FastAPI

Agregar compatibilidad con SSE a su proyecto FastAPI

A continuación, ampliemos el main.pyarchivo para agregar compatibilidad con SSE. Para hacerlo, puede agregar soporte SSE a su proyecto agregando la siguiente línea a su main.pyarchivo:

from sse_starlette.sse import EventSourceResponse

Luego puede usar la EventSourceResponseclase para crear una respuesta que enviará eventos SSE. Vamos a crear un nuevo punto final que enviará un evento cada segundo:

STREAM_DELAY = 1  # second
RETRY_TIMEOUT = 15000  # milisecond

@app.get('/stream')
async def message_stream(request: Request):
    def new_messages():
        # Add logic here to check for new messages
        yield 'Hello World'
    async def event_generator():
        while True:
            # If client closes connection, stop sending events
            if await request.is_disconnected():
                break

            # Checks for new messages and return them to client if any
            if new_messages():
                yield {
                        "event": "new_message",
                        "id": "message_id",
                        "retry": RETRY_TIMEOUT,
                        "data": "message_content"
                }

            await asyncio.sleep(STREAM_DELAY)

    return EventSourceResponse(event_generator())

Ahora, si visita el /streampunto final en su navegador, verá un evento enviado cada segundo sin tener que volver a cargar la página.

FastAPI con transmisión de datos y Materialise

Para obtener más información sobre la transmisión de datos, puede consultar este tutorial aquí sobre cómo usar FastAPI con Materialise:

Cómo utilizar FastAPI con Materialise para el procesamiento de datos en tiempo real

El tutorial también incluye un proyecto de demostración que puede ejecutar para tener una idea de cómo funciona todo.

Aquí hay un diagrama rápido del proyecto:

FastAPI con Materialise

¿Qué es Materializar?

Materialise es una base de datos de transmisión que toma datos provenientes de diferentes fuentes como Kafka, PostgreSQL, cubos S3 y más, y permite a los usuarios escribir vistas que agregan/materializan esos datos y le permiten consultar esas vistas usando SQL puro con muy baja latencia.

Transmisión de datos con Materialise

Para el proyecto de demostración, estamos usando la [TAIL](https://materialize.com/docs/sql/tail/#conceptual-framework)declaración. TAILtransmite actualizaciones desde una fuente, tabla o vista a medida que ocurren, lo que le permite consultar los datos a medida que se actualizan y es perfecto para el ejemplo de SSE.

Aquí está el código para el /streampunto final que se utiliza TAILpara transmitir datos:

@app.get('/stream')
async def message_stream(request: Request):
    def new_messages():
        # Check if data in table
        results = engine.execute('SELECT count(*) FROM sensors_view_1s')
        if results.fetchone()[0] == 0:
            return None
        else:
            return True

    async def event_generator():
        while True:
            # If client was closed the connection
            if await request.is_disconnected():
                break

            # Checks for new messages and return them to client if any
            if new_messages():
                connection = engine.raw_connection()
                with connection.cursor() as cur:
                    cur.execute("DECLARE c CURSOR FOR TAIL sensors_view_1s")
                    cur.execute("FETCH ALL c")
                    for row in cur:
                        yield row

            await asyncio.sleep(MESSAGE_STREAM_DELAY)

    return EventSourceResponse(event_generator())

Como puede ver, acabamos de ampliar la new_messagefunción para comprobar si hay mensajes nuevos en la sensors_view_1svista. Si no hay mensajes nuevos, regresaremos Noney EventSourceResponseno enviaremos ningún evento. Si hay mensajes nuevos, regresaremos Truey EventSourceResponseenviaremos los mensajes nuevos.

Luego, en la event_generatorfunción asíncrona, estamos usando TAILla FETCH ALLdeclaración para obtener todos los mensajes en la sensors_view_1svista. Estamos utilizando la DECLARE CURSORdeclaración para crear un cursor que transmitirá los datos a medida que se actualizan.

Conclusión

Para obtener más información sobre FastAPI, consulte la documentación de FastAPI .

Para obtener más información sobre cómo usar FastAPI con Materialise, consulte este tutorial

Fuente: https://hackernoon.com/how-to-use-server-sent-events-sse-with-fastapi

#fastapi 

Cómo Usar Eventos Enviados Por El Servidor (SSE) Con FastAPI
渚  直樹

渚 直樹

1651856400

【FastAPI超入門】80分でFastAPIによるWeb API開発講座

 本講座は、Udemyにて公開したばかりの新講座『FastAPIによるWeb API開発講座』から一部抜粋した構成となっております!
FastAPIの基本的な使い方を抑えることができ、「Web API開発ってなんだか面白そう」「自分にもAPI開発できるかも」と思っていただけることをゴールに定めています。

00:00:00 概要説明
00:02:16 FastAPIとは
00:11:55 VSCodeのインストール
00:15:11 型ヒント(type hints)
00:32:43 必要なライブラリのインストール
00:33:57 FastAPIを起動してみる
00:45:42 APIドキュメントの自動生成
00:51:11 パスパラメータ
01:06:38 クエリパラメータ
01:16:15 必須ではないオプションパラメータ
01:21:18 エンディング

#fastapi  #python #webapi  #api 

【FastAPI超入門】80分でFastAPIによるWeb API開発講座

How to Build APIs with Python | FastAPI Tutorial

In this project, we'll be creating an application using FastAPI. APIs are the backbone of internet services, and I think that the FastAPI framework (released in 2018) is one of the best ways for Python users to easily make custom APIs with high performance.

📚 Chapters

00:00 Introduction
01:15 Install FastAPI
02:16 Creating our first API
06:12 Planning our APIs
08:04 GET method (list books)
09:45 Interactive API documentation
11:12 Call API from terminal
11:46 API path parameters
14:34 Raising exceptions
18:51 POST method (add book)
21:04 Data persistence with JSON
22:13 Using JSON to save files
25:04 JSON request body
27:11 API data modeling
33:44 Rejecting invalid requests
34:19 API query parameters
38:18 Wrapping up

🔗 Links
👉 Project Code: https://github.com/pixegami/fastapi-tutorial 
👉 FastAPI: https://fastapi.tiangolo.com/ 

Subscribe: https://www.youtube.com/c/Pixegami/featured 

#python  #fastapi 

How to Build APIs with Python | FastAPI Tutorial
Jacob Banks

Jacob Banks

1650424605

Asynchronous Event Dispatching/Handling Library for FastAPI and Starlette

FastAPI Events

An event dispatching/handling library for FastAPI, and Starlette.

Features:

  • straightforward API to emit events anywhere in your code
  • events are handled after responses are returned (doesn't affect response time)
  • supports event piping to remote queues
  • powerful built-in handlers to handle events locally and remotely
  • coroutine functions (async def) are the first-class citizen
  • write your handlers, never be limited to just what fastapi_events provides
  • (>=0.3.0) supports event payload validation via Pydantic (See here)

Installation

pip install fastapi-events

To use it with AWS handlers, install:

pip install fastapi-events[aws]

Usage

fastapi-events supports both FastAPI and Starlette. To use it, simply configure it as middleware.

Configuring fastapi-events for FastAPI:

from fastapi import FastAPI
from fastapi.requests import Request
from fastapi.responses import JSONResponse

from fastapi_events.dispatcher import dispatch
from fastapi_events.middleware import EventHandlerASGIMiddleware
from fastapi_events.handlers.local import local_handler


app = FastAPI()
app.add_middleware(EventHandlerASGIMiddleware, 
                   handlers=[local_handler])   # registering handler(s)


@app.get("/")
def index(request: Request) -> JSONResponse:
    dispatch("my-fancy-event", payload={"id": 1})  # Emit events anywhere in your code
    return JSONResponse()    

Configuring fastapi-events for Starlette:

from starlette.applications import Starlette
from starlette.middleware import Middleware
from starlette.requests import Request
from starlette.responses import JSONResponse

from fastapi_events.dispatcher import dispatch
from fastapi_events.handlers.local import local_handler
from fastapi_events.middleware import EventHandlerASGIMiddleware

app = Starlette(middleware=[
    Middleware(EventHandlerASGIMiddleware,
               handlers=[local_handler])  # registering handlers
])

@app.route("/")
async def root(request: Request) -> JSONResponse:
    dispatch("new event", payload={"id": 1})   # Emit events anywhere in your code
    return JSONResponse()

Dispatching events

Events can be dispatched anywhere in the code, as long as they are dispatched before a response is made.

# anywhere in code

from fastapi_events.dispatcher import dispatch

dispatch(
    "cat-requested-a-fish",  # Event name, accepts any valid string
    payload={"cat_id": "fd375d23-b0c9-4271-a9e0-e028c4cd7230"}  # Event payload, accepts any arbitrary data
)

dispatch("a_cat_is_spotted")  # This works too!

Event Payload Validation With Pydantic

Event payload validation is possible since version 0.3.0. To enable, simply register a Pydantic models with the corresponding event name.

import uuid
from enum import Enum
from datetime import datetime

from pydantic import BaseModel
from fastapi_events.registry.payload_schema import registry as payload_schema


class UserEvents(Enum):
    SIGNED_UP = "USER_SIGNED_UP"
    ACTIVATED = "USER_ACTIVATED"


# Registering your event payload schema
@payload_schema.register(event_name=UserEvents.SIGNED_UP)
class SignUpPayload(BaseModel):
    user_id: uuid.UUID
    created_at: datetime

Wildcard in event name is currently not supported

Payload will be validated automatically without any changes made while invoking the dispatcher.

# Events with payload schema registered
dispatch(UserEvents.SIGNED_UP)  # raises ValidationError, missing payload
dispatch(UserEvents.SIGNED_UP,
         {"user_id": "9e79cdbb-b216-40f7-9a05-20d223dee89a"})  # raises ValidationError, missing `created_at`
dispatch(UserEvents.SIGNED_UP,
         {"user_id": "9e79cdbb-b216-40f7-9a05-20d223dee89a", created_at: datetime.utcnow()})  # OK!

# Events without payload schema -> No validation will be performed
dispatch(UserEvents.ACTIVATED,
         {"user_id": "9e79cdbb-b216-40f7-9a05-20d223dee89a"})  # OK! no validation will be performed

Reminder: payload validation is optional. Payload of events without its schema registered will not be validated.

Handling Events

Handle events locally

The flexibility of fastapi-events allows us to customise how the events should be handled. For starters, you might want to handle your events locally.

# ex: in handlers.py

from fastapi_events.handlers.local import local_handler
from fastapi_events.typing import Event


@local_handler.register(event_name="cat*")
def handle_all_cat_events(event: Event):
    """
    this handler will match with an events prefixed with `cat`.
    ex: "cat_eats_a_fish", "cat_is_cute", etc
    """
    # the `event` argument is nothing more than a tuple of event name and payload
    event_name, payload = event

    # TODO do anything you'd like with the event


@local_handler.register(event_name="cat*")  # Tip: You can register several handlers with the same event name
def handle_all_cat_events_another_way(event: Event):
    pass


@local_handler.register(event_name="*")
async def handle_all_events(event: Event):
    # event handlers can be coroutine function too (`async def`)
    pass

Piping Events To Remote Queues

For larger projects, you might have services dedicated to handling events separately.

For instance, fastapi-events comes with AWS SQS forwarder to forward events to a remote queue.

Register SQSForwardHandler as handlers:

app = FastAPI()
app.add_middleware(EventHandlerASGIMiddleware, 
                   handlers=[SQSForwardHandler(queue_url="test-queue",
                                               region_name="eu-central-1")])   # registering handler(s)

Start dispatching events! Events will be serialised into JSON format by default:

["event name", {"payload": "here is the payload"}]

Tip: to pipe events to multiple queues, provide multiple handlers while adding EventHandlerASGIMiddleware.

Built-in handlers

Here is a list of built-in event handlers:

LocalHandler / local_handler:

  • import from fastapi_events.handlers.local
  • for handling events locally. See examples above
  • event name pattern matching is done using Unix shell-style matching (fnmatch)

SQSForwardHandler:

  • import from fastapi_events.handlers.aws
  • to forward events to an AWS SQS queue

EchoHandler:

  • import from fastapi_events.handlers.echo
  • to forward events to stdout with pprint. Great for debugging purpose

Creating your own handler

Creating your own handler is nothing more than inheriting from the BaseEventHandler class in fastapi_events.handlers.base.

To handle events, fastapi_events calls one of these methods, in the following priority order:

handle_many(events): The coroutine function should expect the backlog of the events collected.

handle(event): In cases where handle_many() weren't defined in your custom handler, handle() will be called by iterating through the events in the backlog.

from typing import Iterable

from fastapi_events.typing import Event
from fastapi_events.handlers.base import BaseEventHandler


class MyOwnEventHandler(BaseEventHandler):
    async def handle(self, event: Event) -> None:
        """
        Handle events one by one
        """
        pass

    async def handle_many(self, events: Iterable[Event]) -> None:
        """
        Handle events by batch
        """
        pass

Cookbook

1) Suppressing Events / Disabling dispatch() Globally

In case you want to suppress events globally especially during testing, you can do so without having to mock or patch the dispatch() function. Simple set the environment variable FASTAPI_EVENTS_DISABLE_DISPATCH to 1, True or any truthy values.

2) Validating Event Payload During Dispatch

Requires Pydantic, which comes with FastAPI. If you're using Starlette, you might need to install Pydantic

See Event Payload Validation With Pydantic

FAQs:

I'm getting LookupError when dispatch() is used:

    def dispatch(event_name: str, payload: Optional[Any] = None) -> None:
>       q: Deque[Event] = event_store.get()
E       LookupError: <ContextVar name='fastapi_context' at 0x400a1f12b0>

Answer:

dispatch() relies on ContextVars to work properly. There are many reasons why LookupError can occur. A common reason is dispatch() is called outside the request-response lifecycle of FastAPI/Starlette, such as calling dispatch() after a response has been returned.

If you're getting this during testing, you may consider disabling dispatch() during testing. See Suppressing Events / Disabling dispatch() Globally for details.

My event handlers are not registered / Local handlers are not being executed:

Answer:

Make sure the module where your local event handlers are defined is loaded during runtime. A simple fix is to import the module in your __init__.py. This will ensure the modules are properly loaded during runtime.

Feedback, Questions?

Any form of feedback and questions are welcome! Please create an issue here.

Download Details: 
Author: melvinkcx
Source Code: https://github.com/melvinkcx/fastapi-events 
License: MIT
#python #starlette #fastapi

Asynchronous Event Dispatching/Handling Library for FastAPI and Starlette
Louis Jones

Louis Jones

1649407689

How to Build Web APIs with FastAPI

Starting With Fast API to Create a Simple REST API

Creating APIs, or application programming interfaces, is an important part of making your software accessible to a broad range of users. In this video , you’ll learn the main concepts of FastAPI and how to quickly create a web API.

The rest of the course covers how to:

- Use path parameters to get a unique URL path per item
- Receive JSON data in your requests using pydantic
- Use API best practices, including validation, serialization, and documentation
- Continue learning about FastAPI for your use cases

This is a portion of the complete course, which you can find here:
https://realpython.com/courses/python-rest-apis-with-fastapi/

#python #fastapi 

How to Build Web APIs with FastAPI

Building Full Stack Applications with Python and React

Building Full Stack Applications With Python and ReactJS

You will learn how to a build full stack application using Python Fast API Framework and ReactJS

#docker #python #react #fastapi 

Building Full Stack Applications with Python and React
Code  Camp

Code Camp

1648133374

How to Create a Microservices App using Python FastAPI with React

Microservices with FastAPI – Full Course

Learn how to create a simple Microservices app using Python FastAPI with React on the frontend. We will use RedisJSON as a Database and dispatch events with Redis Streams. RedisJSON is a NoSQL database just like MongoDB and Redis Streams is an Event Bus just like RabbitMQ or Apache Kafka.

⭐️ Course Contents ⭐️
⌨️ (00:00) Intro
⌨️ (01:30) App Demo
⌨️ (03:29) Inventory Microservice Setup
⌨️ (05:46) Redis Cloud
⌨️ (07:13) Connect to Redis Cloud
⌨️ (09:04) Products CRUD
⌨️ (20:05) Payment Microservice Setup
⌨️ (25:40) Internal Http Requests
⌨️ (30:54) Background Tasks
⌨️ (36:50) Redis Streams
⌨️ (58:34) Frontend

💻 Code: https://github.com/scalablescripts/fastapi-microservices

#microservices #fastapi #python #react #redis #json #database

How to Create a Microservices App using Python FastAPI with React

Fastapi Utils: Reusable Utilities For FastAPI

Reusable utilities for FastAPI


FastAPI is a modern, fast web framework for building APIs with Python 3.6+.

But if you're here, you probably already knew that!


Features

This package includes a number of utilities to help reduce boilerplate and reuse common functionality across projects:

  • Class Based Views: Stop repeating the same dependencies over and over in the signature of related endpoints.
  • Response-Model Inferring Router: Let FastAPI infer the response_model to use based on your return type annotation.
  • Repeated Tasks: Easily trigger periodic tasks on server startup
  • Timing Middleware: Log basic timing information for every request
  • SQLAlchemy Sessions: The FastAPISessionMaker class provides an easily-customized SQLAlchemy Session dependency
  • OpenAPI Spec Simplification: Simplify your OpenAPI Operation IDs for cleaner output from OpenAPI Generator

It also adds a variety of more basic utilities that are useful across a wide variety of projects:

  • APIModel: A reusable pydantic.BaseModel-derived base class with useful defaults
  • APISettings: A subclass of pydantic.BaseSettings that makes it easy to configure FastAPI through environment variables
  • String-Valued Enums: The StrEnum and CamelStrEnum classes make string-valued enums easier to maintain
  • CamelCase Conversions: Convenience functions for converting strings from snake_case to camelCase or PascalCase and back
  • GUID Type: The provided GUID type makes it easy to use UUIDs as the primary keys for your database tables

See the docs for more details and examples.

Requirements

This package is intended for use with any recent version of FastAPI (depending on pydantic>=1.0), and Python 3.6+.

Installation

pip install fastapi-utils

Author: dmontagu
Source Code: https://github.com/dmontagu/fastapi-utils
License: MIT License

#python #fastapi 

Fastapi Utils: Reusable Utilities For FastAPI