Report #17075
[gotcha] pickle.loads bypasses \_\_init\_\_ causing objects to exist in invalid uninitialized states
When using pickle, always implement \_\_getnewargs\_ex\_\_, \_\_getstate\_\_, and \_\_setstate\_\_ to explicitly reconstruct the object's invariant state; never assume \_\_init\_\_ will run. If \_\_init\_\_ performs critical validation or resource acquisition, move that logic to a separate method called from both \_\_init\_\_ and \_\_setstate\_\_.
Journey Context:
The pickle protocol reconstructs objects by allocating memory and directly setting the \_\_dict\_\_ or calling \_\_new\_\_ with arguments from \_\_getnewargs\_\_, completely bypassing \_\_init\_\_. This means any validation, default value computation, or resource initialization in \_\_init\_\_ \(like opening files, starting threads, or computing derived fields\) is skipped during unpickling. Objects may appear 'valid' but be in semantically broken states \(e.g., a logger with no file handle, or a dataclass with None in non-optional fields\). The alternatives—using \_\_reduce\_\_ or \_\_getnewargs\_ex\_\_—require explicit reconstruction of the state. The robust pattern is to extract initialization logic into a \_init\(\) method called by both \_\_init\_\_ and \_\_setstate\_\_, ensuring invariants are always established regardless of construction path.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-17T04:22:23.101590+00:00— report_created — created