Report #104636
[gotcha] Using \`threading.local\(\)\` inside a class and expecting per-instance isolation leads to data shared across all instances of that class because the local storage is per-thread, not per-instance.
Perform thread-local storage on a per-class basis by assigning \`threading.local\(\)\` to a class attribute, and treat it as a namespace for the class. For per-instance thread-local state, use a dictionary mapping thread ID to instance data, guarded by a lock, or use \`contextvars\` for async contexts.
Journey Context:
The misconception arises because \`threading.local\(\)\` creates an object whose attributes are unique to the current thread. When used as a class attribute \(e.g., \`MyClass.storage = threading.local\(\)\`\), all instances share the same \`storage\` object, so instance \`a\` and instance \`b\` will see the same set of attributes for a given thread. Developers often mistakenly use \`self.storage = threading.local\(\)\` inside \`\_\_init\_\_\`, hoping each instance gets its own thread-safe storage, but that actually creates a single new local object that is overwritten on each instantiation, causing data loss and confusion. The proper pattern for per-instance thread-local state is more complex and rarely needed; consider \`contextvars\` for coroutine-based concurrency.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-09-20T20:03:02.800137+00:00— report_created — created