Xpresso is an ASGI web framework built on top of Starlette, Pydantic and di, with heavy inspiration from FastAPI.
Some of the standout features are:
- ASGI support for high performance (within the context of Python web frameworks)
- OpenAPI documentation generation
- Automatic parsing and validation of request bodies and parameters, with hooks for custom extractors
- Full support for OpenAPI parameter serialization
- Highly typed and tested codebase with great IDE support
- A powerful dependency injection system, backed by di
Python 3.7+
pip install xpresso
You'll also want to install an ASGI server, such as Uvicorn.
pip install uvicorn
Create a file named example.py
:
from pydantic import BaseModel
from xpresso import App, Path, FromPath, FromQuery
class Item(BaseModel):
item_id: int
name: str
async def read_item(item_id: FromPath[int], name: FromQuery[str]) -> Item:
return Item(item_id=item_id, name=name)
app = App(
routes=[
Path(
"/items/{item_id}",
get=read_item,
)
]
)
Run the application:
uvicorn example:app
Navigate to http://127.0.0.1:8000/items/123?name=foobarbaz in your browser. You will get the following JSON response:
{"item_id":123,"name":"foobarbaz"}
Now navigate to http://127.0.0.1:8000/docs to poke around the interactive Swagger UI documentation:
For more examples, tutorials and reference materials, see our documentation.
Xpresso is mainly inspired by FastAPI. FastAPI pioneered several ideas that are core to Xpresso's approach:
- Leverage Pydantic for JSON parsing, validation and schema generation.
- Leverage Starlette for routing and other low level web framework functionality.
- Provide a simple but powerful dependency injection system.
- Use that dependency injection system to provide extraction of request bodies, forms, query parameters, etc.
Xpresso takes these ideas and refines them by:
- Decoupling the dependency injection system from the request/response cycle, leading to an overall much more flexible and powerful dependency injection system, packaged up as the standalone di library.
- Decoupling the framework from Pydantic by using
Annotated
(PEP 593) instead of default values (param: FromQuery[str]
instead ofparam: str = Query(...)
). - Middleware on Routers so that you can use generic ASGI middleware in a routing-aware manner (for example, installing profiling middleware on only some paths without using regex matching).
- Support for lifespans on any Router or mounted App (this silently fails in FastAPI and Starlette)
- dependency injection into the application lifespan and support for multiple dependency scopes.
- Formalizing the framework for extracting parameters and bodies from requests into the Binder API so that 3rd party extensions can do anything the framework does.
- Support for customizing parameter and form serialization.
- Better performance by implementing dependency resolution in Rust, executing dependencies concurrently and controlling threading of sync dependencies on a per-dependency basis.
When I originally concieved Xpresso I wasn't sure what the goal was. I didn't necessarily want to replace FastAPI, I know how much work open source is and was not and am not willing to commit to something like that. So I always thought of the project more as a testing ground for interesting ideas for ASGI web frameworks in general and FastAPI in particular.
I am happy to report that in this sense it has been a smash hit. In the time since writing the above differences:
- Starlette added support for middleware on routers.
- The ASGI spec, Starlette and FastAPI added support for returning data from lifespans, which I think may be an even better idea than dependency scopes.
- FastAPI added support for PEP593 annotations, taking direct inspiration from Xpresso's approach.
- I've established a strong working relationship with Sebastián, FastAPI's author, and I foresee more ideas from Xpresso leaking into FastAPI in some way or another.
So where does that leave Xpresso? It's going to stay around, but it's less likely to become a stable production ready framework: it can provide more value to the community as an exprimental proving ground for ideas than as yet another "production ready" web framework.