3 ms·
What kinds of Python programs would benefit from Signals? Most of the Python I've written is either small CLI tools that run to completion, or boring web server
by jitl 2y ago
What kinds of Python programs would benefit from Signals? Most of the Python I've written is either small CLI tools that run to completion, or boring web servers using frameworks like Django that are request-response oriented, which also has a "run-to-completion" model for a request's handler code.
Also, I looked at your implementation, and your ComputedSignal implementation is not sound - it can give inconsistent results with respect to the input signals depending on the ordering of reads when you have a ComputedSignal that depends on other ComputedSignal.
- buibuibui 2y agoIn my case, I’ve built Python applications that poll multiple sensor data, perform calculations, and push results to the frontend. The frontend is also allowed to configure the measurements on the fly, so I needed some form of reactivity in my backend to handle dynamic changes smoothly. Could you share an example of the problem you’re referring to?
- jitl 2y agoI didn’t have time to work up a repro, but the issue is a classic one with the basic algorithm you use for your ComputeSignal graph. The issue is that during the fan-out after a change at a root, a ComputeSignal that’s recomputing can read a stale out of date value from a ComputeSignal that has not yet recomputed for the change. The simplest solution to implement is to do two phase propagation, the first phase marks all ComputeSignal as “dirty” so any read of them must re-compute. Then in the second phase you do what you’re already doing which is to walk down, re-computing, and stop at ComputeSignals that didn’t change. There are other approaches like using a logical clock that have different balances between time complexity at write time and time complexity at read time. Besides the correctness issue, the eager depth first strategy can re-compute the same ComputeSignal multiple times for a single change to a root. This can also be solved with the dirty phase, because once a dirty ComputeSignal becomes clean you don’t need to re-compute it again during that write’s fan-out.
- jitl 2y agoShiny from the above commenter is a good example of the dirty / “invalidate” style of algorithm. https://github.com/posit-dev/py-shiny/blob/main/shiny/reactive/_reactives.py https://github.com/posit-dev/py-shiny/blob/main/shiny/reacti... https://github.com/posit-dev/py-shiny/blob/main/shiny/reactive/_core.py https://github.com/posit-dev/py-shiny/blob/main/shiny/reacti...
- jcheng 2y agoThere are several high-level web application frameworks for Python that are based around this concept. It's particularly useful for data-oriented apps that let the user tweak parameters and update (arbitrarily complex) calculations and visualizations in response. I personally work on one called Shiny (https://shiny.posit.co/py/ https://shiny.posit.co/py/) but there are others including Reflex.dev and Solara.dev. (I haven't looked at Reaktiv beyond the readme but it's clearly based on the same concepts, albeit it's "only" the reactive primitives and doesn't provide the rest of the stack like the frameworks I mentioned do)