1652475120
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.
"[...] 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)
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. ⌨️ 🚀
Python 3.6+
FastAPI stands on the shoulders of giants:
$ pip install fastapi
---> 100%
You will also need an ASGI server, for production such as Uvicorn or Hypercorn.
$ pip install "uvicorn[standard]"
---> 100%
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 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.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:
/
and /items/{item_id}
.GET
operations (also known as HTTP methods)./items/{item_id}
has a path parameter item_id
that should be an int
./items/{item_id}
has an optional str
query parameter q
.Now go to http://127.0.0.1:8000/docs.
You will see the automatic interactive API documentation (provided by Swagger UI):
And now, go to http://127.0.0.1:8000/redoc.
You will see the alternative automatic documentation (provided by ReDoc):
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).
Now go to http://127.0.0.1:8000/docs.
And now, go to http://127.0.0.1:8000/redoc.
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:
str
, int
, float
, bool
, list
, etc).datetime
objects.UUID
objects.Coming back to the previous code example, FastAPI will:
item_id
in the path for GET
and PUT
requests.item_id
is of type int
for GET
and PUT
requests.q
(as in http://127.0.0.1:8000/items/foo?q=somequery
) for GET
requests.q
parameter is declared with = None
, it is optional.None
it would be required (as is the body in the case with PUT
).PUT
requests to /items/{item_id}
, Read the body as JSON:name
that should be a str
.price
that has to be a float
.is_offer
, that should be a bool
, if present.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:
For a more complete example including more features, see the Tutorial - User Guide.
Spoiler alert: the tutorial - user guide includes:
maximum_length
or regex
.requests
and pytest
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.
Used by Pydantic:
ujson
- for faster JSON "parsing".email_validator
- for email validation.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]"
.
This project is licensed under the terms of the MIT license.
Author: tiangolo
Source Code: https://github.com/tiangolo/fastapi
License: MIT License
1652457600
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. ⛏
CousCous
or Tajine
.# clone the repo
$ git clone https://github.com/GDGSNF/ChefAPI
# move to the project folder
$ cd ChefAPI
pipenv
a global python project pip install pipenv
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
.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 using uvicorn
$ uvicorn main:app
# To run the Application under a reload enviromment use -- reload
$ uvicorn main:app --reload
$ docker build
chefapi:latest
in the list.$ docker images
-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
$ docker container ps
Includes preconfigured packages to kick start ChefAPI by just setting appropriate configuration.
Package | Usage |
---|---|
uvicorn | a lightning-fast ASGI server implementation, using uvloop and httptools. |
Python-Jose | a JavaScript Object Signing and Encryption implementation in Python. |
SQLAlchemy | is the Python SQL toolkit and Object Relational Mapper that gives application developers the full power and flexibility of SQL. |
starlette | a lightweight ASGI framework/toolkit, which is ideal for building high performance asyncio services. |
passlib | a password hashing library for Python 2 & 3, which provides cross-platform implementations of over 30 password hashing algorithms |
bcrypt | Good password hashing for your software and your servers. |
python-multipart | streaming multipart parser for Python. |
yapf
packages for linting and formatting
Author: yezz123
Source Code: https://github.com/yezz123/ChefAPI
License: MIT license
1652032800
NLP as a Service
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.
Fastapi
and Streamlit
making the complete code base in Python.
Docker Compose
to spin up the Fastapi based backend service.streamlit run command
.
Download the models
src_fastapi
folder.Running the backend service.
src_fastapi
folderDocker Compose
comnandRunning the frontend app.
src_streamlit
folderAuthor: abhimishra91
Source Code: https://github.com/abhimishra91/insight
License: GPL-3.0 license
1652010720
flake8-fastapi
A flake8 plugin that helps you avoid simple FastAPI mistakes.
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
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!"
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)
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()
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=['*']
)
Currently, there's no automatic solution to document the HTTPException
s, 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.
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
1651996800
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
To deploy the app, one option is deployment on Heroku (with Dockhero). To do so:
docker-compose.yml
to dockhero-compose.yml
<my-app>
) on a Heroku accountheroku plugins:install dockhero
heroku dh:compose up -d --app <my-app>
to deploy the appheroku dh:open --app <my-app>
8000/docs
, e.g. http://dockhero-<named-assigned-to-my-app>-12345.dockhero.io:8000/docs
(not https
):8501
to visit the streamlit interfaceheroku logs -p dockhero --app <my-app>
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
1651878300
サーバー送信イベント(SSE)は、ページをリロードせずにブラウザーにデータを送信する方法です。これにより、ストリーミングデータを使用して、さまざまなシナリオで使用できるリアルタイムアプリケーションを構築できます。
FastAPIは、APIの構築を容易にするPythonフレームワークです。
このチュートリアルでは、FastAPIを使用して、毎秒メッセージを送信する単純なSSEサーバーを作成します。
このチュートリアルに従うには、Pythonとpipをマシンにインストールする必要があります。
https://www.python.org/downloads/
FastAPIとそのすべての依存関係をインストールするには、次のコマンドを使用できます。
pip install "fastapi[all]"
これには、uvicorn
サーバーの実行に使用されるサーバーも含まれます。
sse-starlette
FastAPIをインストールしたら、sse-starlette
拡張機能をインストールして、FastAPIプロジェクトにSSEのサポートを追加できます。
pip install sse-starlette
asyncio
プロジェクトに追加しましょう:
pip install asyncio
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"
}
/docs
FastAPIは、APIドキュメントを表示するエンドポイントを自動的に生成します。にアクセス/docs
すると、次のように表示されます。
次に、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を使用する方法
チュートリアルには、すべてがどのように機能するかを理解するために実行できるデモプロジェクトも含まれています。
プロジェクトの簡単な図は次のとおりです。
マテリアライズは、Kafka、PostgreSQL、S3バケットなどのさまざまなソースからのデータを取得するストリーミングデータベースであり、ユーザーはそのデータを集約/マテリアライズするビューを記述し、非常に低いレイテンシで純粋なSQLを使用してそれらのビューをクエリできます。
デモプロジェクトでは、[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
イベントを送信しません。新しいメッセージがある場合は、戻っTrue
てEventSourceResponse
新しいメッセージを送信します。
次に、event_generator
async関数でTAIL
、FETCH ALL
ステートメントとともに使用して、sensors_view_1s
ビュー内のすべてのメッセージを取得します。このDECLARE CURSOR
ステートメントを使用して、更新時にデータをストリーミングするカーソルを作成しています。
FastAPIの詳細については、 FastAPIのドキュメントを確認してください。
マテリアライズでFastAPIを使用する方法の詳細については、このチュートリアルを確認してください。
ソース:https ://hackernoon.com/how-to-use-server-sent-events-sse-with-fastapi
#fastapi #sse
1651878000
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.
Para seguir este tutorial, deberá tener Python y pip instalados en su máquina:
https://www.python.org/descargas/
Para instalar FastAPI y todas sus dependencias, puede usar el siguiente comando:
pip install "fastapi[all]"
Esto también incluirá el uvicorn
servidor, que se utiliza para ejecutar el servidor.
sse-starlette
Una vez que haya instalado FastAPI, puede instalar la sse-starlette
extensión para agregar soporte para SSE a su proyecto FastAPI:
pip install sse-starlette
Agreguemos también asyncio
a nuestro proyecto:
pip install asyncio
Una vez que haya instalado FastAPI, puede crear un punto final simple de hola mundo para comenzar.
Cree un nuevo archivo llamado main.py
y 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"}
uvicorn
servidorPara ejecutar el servidor, puede usar el siguiente comando:
uvicorn main:app --reload
Esto ejecutará el servidor en el puerto 8000
. La --reload
bandera 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 /docs
punto final que le mostrará la documentación de la API. Si fuera a visitar /docs
, vería lo siguiente:
A continuación, ampliemos el main.py
archivo para agregar compatibilidad con SSE. Para hacerlo, puede agregar soporte SSE a su proyecto agregando la siguiente línea a su main.py
archivo:
from sse_starlette.sse import EventSourceResponse
Luego puede usar la EventSourceResponse
clase 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 /stream
punto final en su navegador, verá un evento enviado cada segundo sin tener que volver a cargar la página.
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:
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.
Para el proyecto de demostración, estamos usando la [TAIL](https://materialize.com/docs/sql/tail/#conceptual-framework)
declaración. TAIL
transmite 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 /stream
punto final que se utiliza TAIL
para 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_message
función para comprobar si hay mensajes nuevos en la sensors_view_1s
vista. Si no hay mensajes nuevos, regresaremos None
y EventSourceResponse
no enviaremos ningún evento. Si hay mensajes nuevos, regresaremos True
y EventSourceResponse
enviaremos los mensajes nuevos.
Luego, en la event_generator
función asíncrona, estamos usando TAIL
la FETCH ALL
declaración para obtener todos los mensajes en la sensors_view_1s
vista. Estamos utilizando la DECLARE CURSOR
declaración para crear un cursor que transmitirá los datos a medida que se actualizan.
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
1651856400
本講座は、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 エンディング
1650860683
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
1650424605
An event dispatching/handling library for FastAPI, and Starlette.
Features:
async def
) are the first-class citizenfastapi_events
providespip 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()
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 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.
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
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
:
fastapi_events.handlers.local
fnmatch
)SQSForwardHandler
:
fastapi_events.handlers.aws
EchoHandler
:
fastapi_events.handlers.echo
pprint
. Great for debugging purposeCreating 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
dispatch()
GloballyIn 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.
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
1649407689
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
1648867476
You will learn how to a build full stack application using Python Fast API Framework and ReactJS
#docker #python #react #fastapi
1648133374
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
1647435600
Python's FastAPI framework enables engineers to rapidly build new applications by calling functions such as authentication through the Fast API.
1647428400
FastAPI is a modern, fast web framework for building APIs with Python 3.6+.
But if you're here, you probably already knew that!
This package includes a number of utilities to help reduce boilerplate and reuse common functionality across projects:
response_model
to use based on your return type annotation.FastAPISessionMaker
class provides an easily-customized SQLAlchemy Session dependencyIt also adds a variety of more basic utilities that are useful across a wide variety of projects:
pydantic.BaseModel
-derived base class with useful defaultspydantic.BaseSettings
that makes it easy to configure FastAPI through environment variablesStrEnum
and CamelStrEnum
classes make string-valued enums easier to maintainsnake_case
to camelCase
or PascalCase
and backSee the docs for more details and examples.
This package is intended for use with any recent version of FastAPI (depending on pydantic>=1.0
), and Python 3.6+.
pip install fastapi-utils
Author: dmontagu
Source Code: https://github.com/dmontagu/fastapi-utils
License: MIT License