dash icon indicating copy to clipboard operation
dash copied to clipboard

[Feature Request] FastAPI / other ASGI support

Open 3tilley opened this issue 3 years ago • 11 comments

Hello!

We love Dash, it's been perfect for our team of Python developers who want to provide rich web frontends.

We're coming up against the issue that it's difficult to host alongside our other web services though, primarily because we use FastAPI. FastAPI is the most popular of the ASGI frontends but by no means the only one, if a solution could be found to support ASGI as well as WSGI, I think the other webservers could just slot in as well.

I've read up on various topics where this is mentioned, and aside from the non-trivial work to make it generic, it seems like the major blocker is Python 2.7 support, and Python 3.6 needed for async/await. I have every sympathy with having to support Enterprise Python, and I'm sure you're well aware of this, but Python 2.7 has been end of life for 15 months, and 3.5 has been end of life for six months.

Is there a roadmap for Dash 2.0? Would that be the time to support multiple backends and draw a line in the sand on versions?


References

https://community.plotly.com/t/websockets-devices-performance-gains/39669 https://github.com/plotly/dash/issues/1559

3tilley avatar Mar 11 '21 21:03 3tilley

We are indeed working on a Dash 2.0 right now, but we're not quite ready to make the plans public yet - stay tuned, we'll be ready to share sometime this spring 🌸

But I'm happy to say we will drop Py2 support with Dash 2.0, and I believe Py3.6 is a reasonable new minimum. According to https://pypistats.org/packages/dash we still have a couple percent of users installing on 3.5 (and another couple percent on 2.7 🙈 ) but hopefully this change will help encourage them to upgrade!

So if you're interested in contributing a feature that requires Py3.6, in a couple of months we'll happily accept it into the core dash repo 😄

alexcjohnson avatar Mar 12 '21 00:03 alexcjohnson

Thanks!

Do you think that there would be appetite for a switchable backend at that point, instead of just Flask?

3tilley avatar Mar 12 '21 12:03 3tilley

As long as it's done in a way that's backward compatible for folks using the Flask server and interfacing directly with it via app.server, I think it should be fine to generalize to other back ends.

alexcjohnson avatar Mar 12 '21 13:03 alexcjohnson

I'm potentially interested in contributing/testing ASGI support. (I'm using Starlette/Uvicorn.)

oTree-org avatar Mar 17 '21 15:03 oTree-org

Hello, I'm just circling back to this to ask if there is more clarity on Dash 2.0. I can see the announcements have been made, was it decided what versions of Python will be supported? Python 3.6 is EoL at the end of the year, so I wonder if even making 3.7 the minimum is worth considering, especially if the release will be in 2022.

3tilley avatar Aug 07 '21 15:08 3tilley

@alexcjohnson it looks like Python 3.6 is now the minimum. Could this change now potentially go ahead?

3tilley avatar Feb 08 '22 00:02 3tilley

Yes, Py3.6+ since Dash 2.0, so this is certainly a possibility! ASGI support isn't something that Plotly devs are planning to work on in the near future, but if you're up for creating a PR we'd be delighted to help bring it to completion.

alexcjohnson avatar Feb 09 '22 17:02 alexcjohnson

Quart already does most of the heavy lifting of masquerading as a Flask (via patching, to support Flask extensions). so switching Dash to use Quart was actually super trivial - mostly just wrapping async coroutines such as callbacks with ensure_sync . And in particular, most remaining API incompatibilities were addressed in recent commits such as e.g. this and this.

And given that Quart is now officially a pallets/Flask team project, it really is a no-brainer to make a switch if you want to use Dash with ASGI backend.

nirvana-msu avatar Jul 09 '22 23:07 nirvana-msu

Forgive me if this seems like a fairly naive comment, but what is the true difficulty in ASGI conversion? I've been experimenting with various asynchronous implementations like the monkey-patched version of Dash and it seems to me that a large portion of it falls on introducing async/await to the plethora of Dash functions especially where it relates to server request objects.

My main motivation for an asynchronous Dash implementation is that a monkey-patched version has fallen behind without constant updating. I submitted a PR to add duplicate callbacks to Async-Dash and pages are not currently supported except via another PR.

Would love for someone to comment on the overall complexity of the task - I'd love to get my feet dirty and contribute via PR. @alexcjohnson

brendanillies avatar Mar 24 '24 20:03 brendanillies

@brendanillies

what is the true difficulty in ASGI conversion?

We need to keep flask as default server, the implementation would need to abstract everywhere we use flask.

I think it would be best to start with just allowing async callbacks, with flask 2.0 you can install flask[async] to add async routes. Could add the same dash[async] and then check if the callback function is a co routine to await it if necessary. Basically can go from the change in the patched version to take in consideration the new code in dash._callback.py. The function add_context may need remain non-async if flask[async] is not installed, it install asgiref, maybe try import that if it work you can use the async one instead.

T4rk1n avatar Mar 27 '24 16:03 T4rk1n

@brendanillies

what is the true difficulty in ASGI conversion?

We need to keep flask as default server, the implementation would need to abstract everywhere we use flask.

I think it would be best to start with just allowing async callbacks, with flask 2.0 you can install flask[async] to add async routes. Could add the same dash[async] and then check if the callback function is a co routine to await it if necessary. Basically can go from the change in the patched version to take in consideration the new code in dash._callback.py. The function add_context may need remain non-async if flask[async] is not installed, it install asgiref, maybe try import that if it work you can use the async one instead.

Thanks for the info here. Unfortunately I've looked into this and with the number of user interactions and the necessity for plug and play websockets, Quart was the better option for me.

I will definitely be taking this away though and working with it a bit as I think there's flexibility to explore other servers. Maybe I'm underestimating the lift required, but if the need is there I'm happy to take it on. I'll report back with any questions I have!

brendanillies avatar Mar 28 '24 15:03 brendanillies