Skip to content

Commit 65ed1b7

Browse files
[3.13] gh-117983: Defer import of threading for lazy module loading (GH-120233) (GH-121349)
gh-117983: Defer import of threading for lazy module loading (GH-120233) As noted in gh-117983, the import importlib.util can be triggered at interpreter startup under some circumstances, so adding threading makes it a potentially obligatory load. Lazy loading is not used in the stdlib, so this removes an unnecessary load for the majority of users and slightly increases the cost of the first lazily loaded module. An obligatory threading load breaks gevent, which monkeypatches the stdlib. Although unsupported, there doesn't seem to be an offsetting benefit to breaking their use case. For reference, here are benchmarks for the current main branch: ``` ❯ hyperfine -w 8 './python -c "import importlib.util"' Benchmark 1: ./python -c "import importlib.util" Time (mean ± σ): 9.7 ms ± 0.7 ms [User: 7.7 ms, System: 1.8 ms] Range (min … max): 8.4 ms … 13.1 ms 313 runs ``` And with this patch: ``` ❯ hyperfine -w 8 './python -c "import importlib.util"' Benchmark 1: ./python -c "import importlib.util" Time (mean ± σ): 8.4 ms ± 0.7 ms [User: 6.8 ms, System: 1.4 ms] Range (min … max): 7.2 ms … 11.7 ms 352 runs ``` Compare to: ``` ❯ hyperfine -w 8 './python -c pass' Benchmark 1: ./python -c pass Time (mean ± σ): 7.6 ms ± 0.6 ms [User: 5.9 ms, System: 1.6 ms] Range (min … max): 6.7 ms … 11.3 ms 390 runs ``` This roughly halves the import time of importlib.util. (cherry picked from commit 94f50f8) Co-authored-by: Chris Markiewicz <[email protected]>
1 parent e7008d7 commit 65ed1b7

File tree

2 files changed

+5
-1
lines changed

2 files changed

+5
-1
lines changed

Lib/importlib/util.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313

1414
import _imp
1515
import sys
16-
import threading
1716
import types
1817

1918

@@ -257,6 +256,9 @@ def create_module(self, spec):
257256

258257
def exec_module(self, module):
259258
"""Make the module load lazily."""
259+
# Threading is only needed for lazy loading, and importlib.util can
260+
# be pulled in at interpreter startup, so defer until needed.
261+
import threading
260262
module.__spec__.loader = self.loader
261263
module.__loader__ = self.loader
262264
# Don't need to worry about deep-copying as trying to set an attribute
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Defer the ``threading`` import in ``importlib.util`` until lazy loading is
2+
used.

0 commit comments

Comments
 (0)