PEP 805: Safe Parallel Python

There were some issues that came up with the aforementioned previous attempt at making it possible to convert module and class dicts into frozendicts that caused the idea to be abandoned that would need to be resolved. This isn’t intended to be a comprehensive list, but these were the big ones in that case.

  1. PEP-810 lazy imports rely on replacing a lazy_import object in the module dict when accessed. Under that implementation this caused TypeErrors if a lazy_import object was accessed after a module was frozen.
    • Under -X lazy_imports=all this is (almost) every import
    • A caveat was that the implementation from that attempt didn’t manage to replace the reference to the original unfrozen dict held by functions so lazy imports did work inside functions, though not intentionally and not correctly.
    • Both lazy and regular imports can also add attributes to a module dict that aren’t there when the module is created
  2. __annotations__ is lazily created and added to class and module dicts only when first successfully accessed under PEP-649/749 annotations.
  3. Using freeze(__module__) inside a module prevents monkey patching, which is not uncommon (think unittest.mock.patch or what gevent does to the stdlib).

Note that this is specific to modules and to a lesser extent, classes. I’d love a proper way to make instances frozen - frozen dataclasses are slow[1].


I’ll also note that the PEP asserts:

Almost all objects in Python have a __dict__ attribute. Freezing an object will convert its __dict__ into a frozendict.

There’s now the fairly common case via @dataclass(slots=True) or @attrs.define of objects with slots and potentially without a __dict__. I do think it’s probably necessary to explain how such objects will (or won’t) be handled.


  1. compared to non-frozen classes, about twice as slow to make the class and 3.5x as slow to make each instance ↩︎

1 Like