https://github.com/python/cpython/commit/dd2735d177d3d1d1287354443d80cd981012445b
commit: dd2735d177d3d1d1287354443d80cd981012445b
branch: main
author: Daniel Hollas <[email protected]>
committer: hugovk <[email protected]>
date: 2026-04-11T21:05:24Z
summary:

gh-137855: Improve import time of dataclasses by lazy importing  `re` and 
`copy` modules (#148379)

Co-authored-by: Hugo van Kemenade <[email protected]>

files:
A Misc/NEWS.d/next/Library/2026-04-11-12-32-38.gh-issue-137855.tsVny_.rst
M Lib/dataclasses.py

diff --git a/Lib/dataclasses.py b/Lib/dataclasses.py
index 482a4c61039184..7d046d02de35ba 100644
--- a/Lib/dataclasses.py
+++ b/Lib/dataclasses.py
@@ -1,6 +1,4 @@
-import re
 import sys
-import copy
 import types
 import inspect
 import keyword
@@ -8,6 +6,8 @@
 import annotationlib
 import abc
 from reprlib import recursive_repr
+lazy import copy
+lazy import re
 
 
 __all__ = ['dataclass',
@@ -217,9 +217,8 @@ def __repr__(self):
 _POST_INIT_NAME = '__post_init__'
 
 # String regex that string annotations for ClassVar or InitVar must match.
-# Allows "identifier.identifier[" or "identifier[".
-# https://bugs.python.org/issue33453 for details.
-_MODULE_IDENTIFIER_RE = re.compile(r'^(?:\s*(\w+)\s*\.)?\s*(\w+)')
+# This regular expression is compiled on demand so that 're' module can be 
imported lazily
+_MODULE_IDENTIFIER_RE = None
 
 # Atomic immutable types which don't require any recursive handling and for 
which deepcopy
 # returns the same object. We can provide a fast-path for these types in 
asdict and astuple.
@@ -804,10 +803,17 @@ def _is_type(annotation, cls, a_module, a_type, 
is_type_predicate):
     # a eval() penalty for every single field of every dataclass
     # that's defined.  It was judged not worth it.
 
-    match = _MODULE_IDENTIFIER_RE.match(annotation)
+    # String regex that string annotations for ClassVar or InitVar must match.
+    # Allows "identifier.identifier[" or "identifier[".
+    # https://github.com/python/cpython/issues/77634 for details.
+    global _MODULE_IDENTIFIER_RE
+    if _MODULE_IDENTIFIER_RE is None:
+        _MODULE_IDENTIFIER_RE = re.compile(r'(?:\s*(\w+)\s*\.)?\s*(\w+)')
+
+    match = _MODULE_IDENTIFIER_RE.prefixmatch(annotation)
     if match:
         ns = None
-        module_name = match.group(1)
+        module_name = match[1]
         if not module_name:
             # No module name, assume the class's module did
             # "from dataclasses import InitVar".
@@ -817,7 +823,7 @@ def _is_type(annotation, cls, a_module, a_type, 
is_type_predicate):
             module = sys.modules.get(cls.__module__)
             if module and module.__dict__.get(module_name) is a_module:
                 ns = sys.modules.get(a_type.__module__).__dict__
-        if ns and is_type_predicate(ns.get(match.group(2)), a_module):
+        if ns and is_type_predicate(ns.get(match[2]), a_module):
             return True
     return False
 
diff --git 
a/Misc/NEWS.d/next/Library/2026-04-11-12-32-38.gh-issue-137855.tsVny_.rst 
b/Misc/NEWS.d/next/Library/2026-04-11-12-32-38.gh-issue-137855.tsVny_.rst
new file mode 100644
index 00000000000000..0ec08c2d2fd54a
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-04-11-12-32-38.gh-issue-137855.tsVny_.rst
@@ -0,0 +1,2 @@
+Improve import time of :mod:`dataclasses` module by lazy importing :mod:`re`
+and :mod:`copy` modules.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to