"g" is a threadlocal magic object that lets developer add / change / remove attributes during the request lifecycle. Learn more about this "g" here.
There is no OTB equivalent in FastAPI, but thanks to the new contextvars Python 3.7+ module, I made this simple demo.
Any comment or help to improve yhis recipe is welcome.
Hereafter follow the files descriptions and usage for the demo.
The heart of the stuff. Simple ! Just have a look at the doc of the contextvars
module to
understand in seconds what it does.
Nothing special here, except the middleware function init_requestvar
that stores an empty
type.SimpleNamespace
object in our context variable at the start of each request cycle.
The demo of usage of our FastAPI "g" that is a function (sorry for this, but I dunno how to create a lazily evaluated variable).
Note that no data is passed from the foo_route
handler to the double
async function.
Just a simple ordinary uvicorn server for the app that listens on port 8000/
A simple client that queries in a loop http://localhost:8000?q=xyz
and prints the response in an infinite loop. xyz
being the first argument of the shell command line that runs client.py.
If you want to run the demo, just create a Python 3.7+ virtual env and :
pip install fastapi uvicorn requests
Open a first terminal and run the server:
python server.py
Open a second terminal and run the client with an argument:
python client.py arg1
It show:
{'result': 'arg1arg1'}
... (same each second)
Open a third terminal and run the client with another argument:
python client.py foo1
It show:
{'result': 'foo1foo1'}
... (same each second)
Repeat the operation on any new terminal you want...
So I'm here, because like a number of people I wanted some sort of global context object. Personally it was to do a consumer producer paradigm where when the request would come in, put something on a queue, and then I'd have a non blocking task in the background doing stuff.
I tried all sorts of stuff including this which also didn't work for me the way I wanted.
Here's how I did it:
I don't know exactly how this works, but it's python magic that creates a pass by reference object. I use this to store stuff and consume. I don't know if it's safe, but so far I've had no issues
Then I create new threads:
That do stuff because trying to attach to the main loop thats already going was a nightmare for me.