]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-111881: Import _sha2 lazily in random (#111889)
authorVictor Stinner <vstinner@python.org>
Thu, 9 Nov 2023 22:10:21 +0000 (23:10 +0100)
committerGitHub <noreply@github.com>
Thu, 9 Nov 2023 22:10:21 +0000 (23:10 +0100)
The random module now imports the _sha2 module lazily in the
Random.seed() method for str, bytes and bytearray seeds. It also
imports lazily the warnings module in the _randbelow() method for
classes without getrandbits(). Lazy import makes Python startup
faster and reduces the number of imported modules at startup.

Lib/random.py

index 3f7bfd272d65a51053b7a4994024db7d486508a0..875beb2f8cf41c7e818c5d1d50c48067f4ee034f 100644 (file)
@@ -50,7 +50,6 @@ General notes on the underlying Mersenne Twister core generator:
 # Adrian Baddeley.  Adapted by Raymond Hettinger for use with
 # the Mersenne Twister  and os.urandom() core generators.
 
-from warnings import warn as _warn
 from math import log as _log, exp as _exp, pi as _pi, e as _e, ceil as _ceil
 from math import sqrt as _sqrt, acos as _acos, cos as _cos, sin as _sin
 from math import tau as TWOPI, floor as _floor, isfinite as _isfinite
@@ -63,13 +62,6 @@ from bisect import bisect as _bisect
 import os as _os
 import _random
 
-try:
-    # hashlib is pretty heavy to load, try lean internal module first
-    from _sha2 import sha512 as _sha512
-except ImportError:
-    # fallback to official implementation
-    from hashlib import sha512 as _sha512
-
 __all__ = [
     "Random",
     "SystemRandom",
@@ -105,6 +97,7 @@ SG_MAGICCONST = 1.0 + _log(4.5)
 BPF = 53        # Number of bits in a float
 RECIP_BPF = 2 ** -BPF
 _ONE = 1
+_sha512 = None
 
 
 class Random(_random.Random):
@@ -159,6 +152,16 @@ class Random(_random.Random):
             a = -2 if x == -1 else x
 
         elif version == 2 and isinstance(a, (str, bytes, bytearray)):
+            global _sha512
+            if _sha512 is None:
+                try:
+                    # hashlib is pretty heavy to load, try lean internal
+                    # module first
+                    from _sha2 import sha512 as _sha512
+                except ImportError:
+                    # fallback to official implementation
+                    from hashlib import sha512 as _sha512
+
             if isinstance(a, str):
                 a = a.encode()
             a = int.from_bytes(a + _sha512(a).digest())
@@ -257,9 +260,10 @@ class Random(_random.Random):
 
         random = self.random
         if n >= maxsize:
-            _warn("Underlying random() generator does not supply \n"
-                "enough bits to choose from a population range this large.\n"
-                "To remove the range limitation, add a getrandbits() method.")
+            from warnings import warn
+            warn("Underlying random() generator does not supply \n"
+                 "enough bits to choose from a population range this large.\n"
+                 "To remove the range limitation, add a getrandbits() method.")
             return _floor(random() * n)
         rem = maxsize % n
         limit = (maxsize - rem) / maxsize   # int(limit * maxsize) % n == 0