Python's thread-local data and ContextVars appear to achieve the same thing (while having slightly different APIs), with the only user-facing difference being that ContextVars work with async code (coroutines and asyncio), while thread-local data does not.
Is that truly the only practical difference?
Does that mean any code targeting a runtime >= 3.7 (when ContextVar was introduced) is better off using ContextVar everywhere thread-local data might have been used in the past? Or is there a reason to prefer thread-local data still? (Except for scenarios where you specifically want to associate the state with the thread rather than with the context.)
The main problem, IMO, is that the "slightly different APIs" are actually huge differences, and while thread.local is straightforward to use, ContextVars present a low-level painful(*), hard to grasp and verbose alternative.
Other than that, ContextVars seem to be the way to go.
I am working on some code to wrap around ContextVars so they can be a drop-in replacement, but the thing is not production ready yet.
If anyone is interested, the project is paused now, lacking some refinement (docs, etc...) for a published package, but it is fully functional at: https://github.com/jsbueno/extracontext/
(*) Ok "painful" is maybe too subjective, but I swear it feels like that, but it might be because I do not currently have a "real world" use case needing that, and the artificial examples I use are just too artificial grasp the actual use-cases.