@@ -829,9 +829,10 @@ avoid incompatibilities:
829829FAQ
830830===
831831
832- **Q: How does this differ from the rejected PEP 690? **
832+ How does this differ from the rejected PEP 690?
833+ -----------------------------------------------
833834
834- A: PEP 810 takes an explicit, opt-in approach instead of :pep: `690 `'s implicit
835+ PEP 810 takes an explicit, opt-in approach instead of :pep: `690 `'s implicit
835836global approach. The key differences are:
836837
837838- **Explicit syntax **: ``lazy import foo `` clearly marks which imports are
@@ -841,9 +842,10 @@ global approach. The key differences are:
841842- **Simpler implementation **: Uses proxy objects instead of modifying core
842843 dictionary behavior.
843844
844- **Q: What happens when lazy imports encounter errors? **
845+ What happens when lazy imports encounter errors?
846+ ------------------------------------------------
845847
846- A: Import errors (``ImportError ``, ``ModuleNotFoundError ``, syntax errors) are
848+ Import errors (``ImportError ``, ``ModuleNotFoundError ``, syntax errors) are
847849deferred until first use of the lazy name. This is similar to moving an import
848850into a function. The error will occur with a clear traceback pointing to the
849851first access of the lazy object.
@@ -870,26 +872,28 @@ it was first used:
870872 1/0
871873 ZeroDivisionError: division by zero
872874
873- **Q: How do lazy imports affect modules with import-time side effects? **
875+ How do lazy imports affect modules with import-time side effects?
876+ -----------------------------------------------------------------
874877
875- A: Side effects are deferred until first use. This is generally desirable for
878+ Side effects are deferred until first use. This is generally desirable for
876879performance, but may require code changes for modules that rely on import-time
877880registration patterns. We recommend:
878881
879882- Use explicit initialization functions instead of import-time side effects
880883- Call initialization functions explicitly when needed
881884- Avoid relying on import order for side effects
882885
883- **Q: Can I use lazy imports with ** ``from ... import ... `` **statements? **
886+ Can I use lazy imports with ``from ... import ... `` statements?
887+ ---------------------------------------------------------------
884888
885- A: Yes, as long as you don't use ``from ... import * ``. Both ``lazy import
889+ Yes, as long as you don't use ``from ... import * ``. Both ``lazy import
886890foo `` and ``lazy from foo import bar `` are supported. The ``bar `` name will be
887891bound to a lazy object that resolves to ``foo.bar `` on first use.
888892
889- ** Q: Does** ``lazy from module import Class `` ** load the entire module or just
890- the class? **
893+ Does ``lazy from module import Class `` load the entire module or just the class?
894+ --------------------------------------------------------------------------------
891895
892- A: It loads the **entire module **, not just the class. This is because
896+ It loads the **entire module **, not just the class. This is because
893897Python's import system always executes the complete module file -- there's no
894898mechanism to execute only part of a ``.py `` file. When you first access
895899``Class ``, Python:
@@ -924,9 +928,10 @@ at the import statement.
924928loaded. You cannot selectively load only parts of a module -- Python's import
925929system doesn't support partial module execution.
926930
927- **Q: What about type annotations and ** ``TYPE_CHECKING `` **imports? **
931+ What about type annotations and ``TYPE_CHECKING `` imports?
932+ ----------------------------------------------------------
928933
929- A: Lazy imports eliminate the common need for ``TYPE_CHECKING `` guards. You
934+ Lazy imports eliminate the common need for ``TYPE_CHECKING `` guards. You
930935can write:
931936
932937.. code-block :: python
@@ -947,9 +952,10 @@ Instead of:
947952 def process (items : Sequence[str ]) -> Mapping[str , int ]:
948953 ...
949954
950- **Q: What's the performance overhead of lazy imports? **
955+ What's the performance overhead of lazy imports?
956+ ------------------------------------------------
951957
952- A: The overhead is minimal:
958+ The overhead is minimal:
953959
954960- Zero overhead after first use thanks to the adaptive interpreter optimizing
955961 the slow path away.
@@ -964,50 +970,56 @@ performance neutral when lazy imports are not used.
964970 free-threading-benchmarking/blob/main/results/bm-20250922-3.15.0a0-27836e5/
965971 bm-20250922-vultr-x86_64-DinoV-lazy_imports-3.15.0a0-27836e5-vs-base.svg
966972
967- **Q: Can I mix lazy and eager imports of the same module? **
973+ Can I mix lazy and eager imports of the same module?
974+ ----------------------------------------------------
968975
969- A: Yes. If module ``foo `` is imported both lazily and eagerly in the same
976+ Yes. If module ``foo `` is imported both lazily and eagerly in the same
970977program, the eager import takes precedence and both bindings resolve to the
971978same module object.
972979
973- **Q: How do I migrate existing code to use lazy imports? **
980+ How do I migrate existing code to use lazy imports?
981+ ---------------------------------------------------
974982
975- A: Migration is incremental:
983+ Migration is incremental:
976984
9779851. Identify slow-loading modules using profiling tools.
9789862. Add ``lazy `` keyword to imports that aren't needed immediately.
9799873. Test that side-effect timing changes don't break functionality.
9809884. Use :data: `!__lazy_modules__ ` for compatibility with older Python versions.
981989
982- **Q: What about star imports ** (``from module import * ``)?
990+ What about star imports (``from module import * ``)?
991+ ---------------------------------------------------
983992
984- A: Wild card (star) imports cannot be lazy - they remain eager. This is
993+ Wild card (star) imports cannot be lazy - they remain eager. This is
985994because the set of names being imported cannot be determined without loading
986995the module. Using the ``lazy `` keyword with star imports will be a syntax
987996error. If lazy imports are globally enabled, star imports will still be eager.
988997
989- **Q: How do lazy imports interact with import hooks and custom loaders? **
998+ How do lazy imports interact with import hooks and custom loaders?
999+ ------------------------------------------------------------------
9901000
991- A: Import hooks and loaders work normally. When a lazy object is first used,
1001+ Import hooks and loaders work normally. When a lazy object is first used,
9921002the standard import protocol runs, including any custom hooks or loaders that
9931003were in place at reification time.
9941004
995- **Q: What happens in multi-threaded environments? **
1005+ What happens in multi-threaded environments?
1006+ --------------------------------------------
9961007
997- A: Lazy import reification is thread-safe. Only one thread will perform the
1008+ Lazy import reification is thread-safe. Only one thread will perform the
9981009actual import, and the binding is atomically updated. Other threads will see
9991010either the lazy proxy or the final resolved object.
10001011
1001- **Q: Can I force reification of a lazy import without using it? **
1012+ Can I force reification of a lazy import without using it?
1013+ ----------------------------------------------------------
10021014
1003- A: Yes, accessing a module's ``__dict__ `` will reify all lazy objects in that
1015+ Yes, accessing a module's ``__dict__ `` will reify all lazy objects in that
10041016module. Individual lazy objects can be resolved by calling their ``get() ``
10051017method.
10061018
1007- ** Q: What's the difference between** `` globals() `` ** and ** ``mod.__dict__ ``
1008- ** for lazy imports? **
1019+ What's the difference between :func: ` globals ` and ``mod.__dict__ `` for lazy imports?
1020+ ------------------------------------------------------------------------------------
10091021
1010- A: Calling ``globals() `` returns the module's dictionary without reifying lazy
1022+ Calling ``globals() `` returns the module's dictionary without reifying lazy
10111023imports -- you'll see lazy proxy objects when accessing them through the
10121024returned dictionary. However, accessing ``mod.__dict__ `` from external code
10131025reifies all lazy imports in that module first. This design ensures:
@@ -1030,24 +1042,27 @@ This distinction means adding lazy imports and calling ``globals()`` is your
10301042responsibility to manage, while external code accessing ``mod.__dict__ ``
10311043always sees fully loaded modules.
10321044
1033- **Q: Why not use ** ``importlib.util.LazyLoader `` **instead? **
1045+ Why not use ``importlib.util.LazyLoader `` instead?
1046+ --------------------------------------------------
10341047
1035- A: ``LazyLoader `` has significant limitations:
1048+ ``LazyLoader `` has significant limitations:
10361049
10371050- Requires verbose setup code for each lazy import.
10381051- Has ongoing performance overhead on every attribute access.
10391052- Doesn't work well with ``from ... import `` statements.
10401053- Less clear and standard than dedicated syntax.
10411054
1042- **Q: Will this break tools like ** ``isort `` **or ** ``black ``?
1055+ Will this break tools like ``isort `` or ``black ``?
1056+ --------------------------------------------------
10431057
1044- A: Tools will need updates to recognize the ``lazy `` keyword, but the changes
1058+ Tools will need updates to recognize the ``lazy `` keyword, but the changes
10451059should be minimal since the import structure remains the same. The keyword
10461060appears at the beginning, making it easy to parse.
10471061
1048- **Q: How do I know if a library is compatible with lazy imports? **
1062+ How do I know if a library is compatible with lazy imports?
1063+ -----------------------------------------------------------
10491064
1050- A: Most libraries should work fine with lazy imports. Libraries that might
1065+ Most libraries should work fine with lazy imports. Libraries that might
10511066have issues:
10521067
10531068- Those with essential import-time side effects (registration,
@@ -1057,10 +1072,10 @@ have issues:
10571072
10581073When in doubt, test lazy imports with your specific use cases.
10591074
1060- ** Q: What happens if I globally enable lazy imports mode and a library doesn't
1061- work correctly? **
1075+ What happens if I globally enable lazy imports mode and a library doesn't work correctly?
1076+ -----------------------------------------------------------------------------------------
10621077
1063- A: *Note: This is an advanced feature. * You can use the lazy imports filter to
1078+ *Note: This is an advanced feature. * You can use the lazy imports filter to
10641079exclude specific modules that are known to have problematic side effects:
10651080
10661081.. code-block :: python
@@ -1082,15 +1097,17 @@ forces an eager import.
10821097Alternatively, set the global mode to ``"disabled" `` via ``-X
10831098lazy_imports=disabled `` to turn off all lazy imports for debugging.
10841099
1085- **Q: Can I use lazy imports inside functions? **
1100+ Can I use lazy imports inside functions?
1101+ ----------------------------------------
10861102
1087- A: No, the ``lazy `` keyword is only allowed at module level. For
1103+ No, the ``lazy `` keyword is only allowed at module level. For
10881104function-level lazy loading, use traditional inline imports or move the import
10891105to module level with ``lazy ``.
10901106
1091- **Q: What about forwards compatibility with older Python versions? **
1107+ What about forwards compatibility with older Python versions?
1108+ -------------------------------------------------------------
10921109
1093- A: Use the :data: `!__lazy_modules__ ` global for compatibility:
1110+ Use the :data: `!__lazy_modules__ ` global for compatibility:
10941111
10951112.. code-block :: python
10961113
@@ -1112,9 +1129,12 @@ maximum predictability, it's recommended to define :data:`!__lazy_modules__`
11121129once, before any imports. But as it is checked on each import, it can be
11131130modified between ``import `` statements.
11141131
1115- **Q: How do explicit lazy imports interact with PEP-649/PEP-749 **
1132+ How do explicit lazy imports interact with PEP 649 and PEP 749?
1133+ ---------------------------------------------------------------
11161134
1117- A: If an annotation is not stringified, it is an expression that is evaluated
1135+ Python 3.14 implemented deferred evaluation of annotations,
1136+ as specified by :pep: `649 ` and :pep: `749 `.
1137+ If an annotation is not stringified, it is an expression that is evaluated
11181138at a later time. It will only be resolved if the annotation is accessed. In
11191139the example below, the ``fake_typing `` module is only loaded when the user
11201140inspects the ``__annotations__ `` dictionary. The ``fake_typing `` module would
@@ -1128,10 +1148,10 @@ also be loaded if the user uses ``annotationlib.get_annotations()`` or
11281148 pass
11291149 print (foo.__annotations__ ) # Triggers loading the fake_typing module
11301150
1131- ** Q: How do lazy imports interact with** :func: `dir `, :func: `getattr `, ** and
1132- module introspection? **
1151+ How do lazy imports interact with :func: `dir `, :func: `getattr `, and module introspection?
1152+ -----------------------------------------------------------------------------------------
11331153
1134- A: Accessing lazy imports through normal attribute access or ``getattr() ``
1154+ Accessing lazy imports through normal attribute access or ``getattr() ``
11351155will trigger reification. Calling ``dir() `` on a module will reify all lazy
11361156imports in that module to ensure the directory listing is complete. This is
11371157similar to accessing ``mod.__dict__ ``.
@@ -1149,9 +1169,10 @@ similar to accessing ``mod.__dict__``.
11491169 dir (json)
11501170 # Now json is in sys.modules
11511171
1152- **Q: Do lazy imports work with circular imports? **
1172+ Do lazy imports work with circular imports?
1173+ -------------------------------------------
11531174
1154- A: Lazy imports don't automatically solve circular import problems. If two
1175+ Lazy imports don't automatically solve circular import problems. If two
11551176modules have a circular dependency, making the imports lazy might help **only
11561177if ** the circular reference isn't accessed during module initialization.
11571178However, if either module accesses the other during import time, you'll still
@@ -1205,9 +1226,10 @@ which then tries to access ``module_a`` before it's fully initialized.
12051226
12061227The best practice is still to avoid circular imports in your code design.
12071228
1208- **Q: Will lazy imports affect the performance of my hot paths? **
1229+ Will lazy imports affect the performance of my hot paths?
1230+ ---------------------------------------------------------
12091231
1210- A: After first use, lazy imports have **zero overhead ** thanks to the adaptive
1232+ After first use, lazy imports have **zero overhead ** thanks to the adaptive
12111233interpreter. The interpreter specializes the bytecode (e.g., ``LOAD_GLOBAL ``
12121234becomes ``LOAD_GLOBAL_MODULE ``) which eliminates the lazy check on subsequent
12131235accesses. This means once a lazy import is reified, accessing it is just as
@@ -1242,9 +1264,10 @@ You can observe the specialization using ``dis.dis(use_json, adaptive=True)``:
12421264 The specialized ``LOAD_GLOBAL_MODULE `` and ``LOAD_ATTR_MODULE `` instructions
12431265are optimized fast paths with no overhead for checking lazy imports.
12441266
1245- **Q: What about ** ``sys.modules ``? **When does a lazy import appear there? **
1267+ What about :data: `sys.modules `? When does a lazy import appear there?
1268+ ---------------------------------------------------------------------
12461269
1247- A: A lazily imported module does **not ** appear in ``sys.modules `` until it's
1270+ A lazily imported module does **not ** appear in ``sys.modules `` until it's
12481271reified (first used). Once reified, it appears in ``sys.modules `` just like
12491272any eager import.
12501273
@@ -1259,9 +1282,10 @@ any eager import.
12591282
12601283 print (' json' in sys.modules) # True
12611284
1262- **Q: Why you chose ** ``lazy `` **as the keyword name? **
1285+ Why you chose ``lazy `` as the keyword name?
1286+ -------------------------------------------
12631287
1264- A: Not "why"... memorize! :)
1288+ Not "why"... memorize! :)
12651289
12661290Alternate Implementation Ideas
12671291==============================
0 commit comments