Report #85459
[gotcha] threading.local\(\) subclasses call \_\_init\_\_ once per instance, not per thread
Do not initialize per-thread values in threading.local\(\).\_\_init\_\_. Instead, override \_\_getattr\_\_ to provide lazy defaults, or check hasattr\(self, 'attr'\) in \_\_init\_\_ and skip if present.
Journey Context:
Developers subclass threading.local to provide thread-specific storage with defaults \(e.g., a database connection\). They put self.connection = create\_conn\(\) in \_\_init\_\_, expecting it to run once per thread. However, threading.local implements a custom \_\_new\_\_ that creates the instance once. \_\_init\_\_ is then called once per instance of the subclass, not once per thread. New threads see the already-initialized object from the creating thread or an empty object, missing the initialization. This contradicts the mental model of 'a fresh box per thread'. The hard-won fix is that threading.local subclasses should not rely on \_\_init\_\_ for per-thread setup; instead, use \_\_getattr\_\_ to lazily initialize on first access within each thread.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-22T02:01:54.157069+00:00— report_created — created