https://github.com/python/cpython/commit/f717b25712064b88e6dac5a919dbc717e69ebb9c
commit: f717b25712064b88e6dac5a919dbc717e69ebb9c
branch: main
author: Savannah Ostrowski <[email protected]>
committer: savannahostrowski <[email protected]>
date: 2026-07-24T20:33:26Z
summary:

GH-154638: Use lazy imports in argparse (#154639)

Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>

files:
A Misc/NEWS.d/next/Library/2026-07-24-17-02-46.gh-issue-154638.7YnFHH.rst
M Lib/argparse.py
M Lib/test/test_argparse.py

diff --git a/Lib/argparse.py b/Lib/argparse.py
index 42891516b3bb2a..f8739d031e01c5 100644
--- a/Lib/argparse.py
+++ b/Lib/argparse.py
@@ -87,12 +87,17 @@
 
 
 import os as _os
-import re as _re
 import sys as _sys
-from gettext import gettext as _
-from gettext import ngettext
 
 lazy import _colorize
+lazy import copy
+lazy import difflib
+lazy import re as _re
+lazy import shutil
+lazy import textwrap
+lazy import warnings
+lazy from gettext import gettext as _
+lazy from gettext import ngettext
 
 SUPPRESS = '==SUPPRESS=='
 
@@ -143,10 +148,8 @@ def _copy_items(items):
         return []
     # The copy module is used only in the 'append' and 'append_const'
     # actions, and it is needed only when the default value isn't a list.
-    # Delay its import for speeding up the common case.
     if type(items) is list:
         return items[:]
-    import copy
     return copy.copy(items)
 
 
@@ -186,7 +189,6 @@ def __init__(
     ):
         # default setting for width
         if width is None:
-            import shutil
             width = shutil.get_terminal_size().columns
             width -= 2
 
@@ -773,9 +775,6 @@ def _iter_indented_subactions(self, action):
 
     def _split_lines(self, text, width):
         text = self._whitespace_matcher.sub(' ', text).strip()
-        # The textwrap module is used only for formatting help.
-        # Delay its import for speeding up the common usage of argparse.
-        import textwrap
         decolored = self._decolor(text)
         if decolored == text:
             return textwrap.wrap(text, width)
@@ -808,7 +807,6 @@ def _split_lines(self, text, width):
 
     def _fill_text(self, text, width, indent):
         text = self._whitespace_matcher.sub(' ', text).strip()
-        import textwrap
         return textwrap.fill(text, width,
                              initial_indent=indent,
                              subsequent_indent=indent)
@@ -1486,7 +1484,6 @@ class FileType(object):
     """
 
     def __init__(self, mode='r', bufsize=-1, encoding=None, errors=None):
-        import warnings
         warnings.warn(
             "FileType is deprecated. Simply open files after parsing 
arguments.",
             category=PendingDeprecationWarning,
@@ -1893,7 +1890,6 @@ class _ArgumentGroup(_ActionsContainer):
 
     def __init__(self, container, title=None, description=None, **kwargs):
         if 'prefix_chars' in kwargs:
-            import warnings
             depr_msg = (
                 "The use of the undocumented 'prefix_chars' parameter in "
                 "ArgumentParser.add_argument_group() is deprecated."
@@ -2824,7 +2820,6 @@ def _check_value(self, action, value):
 
             if self.suggest_on_error and isinstance(value, str):
                 if all(isinstance(choice, str) for choice in action.choices):
-                    import difflib
                     suggestions = difflib.get_close_matches(value, 
action.choices, 1)
                     if suggestions:
                         args['closest'] = suggestions[0]
@@ -2964,8 +2959,6 @@ def _warning(self, message):
 
 def __getattr__(name):
     if name == "__version__":
-        from warnings import _deprecated
-
-        _deprecated("__version__", remove=(3, 20))
+        warnings._deprecated("__version__", remove=(3, 20))
         return "1.1"  # Do not change
     raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py
index fbeb933841129e..442cbb1aaadfe3 100644
--- a/Lib/test/test_argparse.py
+++ b/Lib/test/test_argparse.py
@@ -3,7 +3,6 @@
 import _colorize
 import contextlib
 import functools
-import inspect
 import io
 import operator
 import os
@@ -12,6 +11,7 @@
 import sys
 import textwrap
 import tempfile
+import types
 import unittest
 import argparse
 import warnings
@@ -85,6 +85,8 @@ class TestLazyImports(unittest.TestCase):
         "_colorize",
         "copy",
         "difflib",
+        "gettext",
+        "re",
         "shutil",
         "textwrap",
         "warnings",
@@ -99,7 +101,7 @@ def test_create_parser(self):
         # Test imports are still unused after
         # creating a parser
         create_parser = "argparse.ArgumentParser()"
-        imported_modules = {"shutil"}
+        imported_modules = {"gettext", "re", "shutil"}
 
         import_helper.ensure_lazy_imports(
             "argparse",
@@ -114,7 +116,7 @@ def test_add_subparser(self):
             parser.add_subparsers(dest='command', required=False)
             """
         )
-        imported_modules = {"shutil"}
+        imported_modules = {"gettext", "re", "shutil"}
 
         import_helper.ensure_lazy_imports(
             "argparse",
@@ -132,7 +134,7 @@ def test_parse_args(self):
             parser.parse_args(['BAR', '--foo', 'FOO'])
             """
         )
-        imported_modules = {"shutil"}
+        imported_modules = {"gettext", "re", "shutil"}
         import_helper.ensure_lazy_imports(
             "argparse",
             self.LAZY_IMPORTS - imported_modules,
@@ -7098,7 +7100,10 @@ def test_all_exports_everything_but_modules(self):
             name
             for name, value in vars(argparse).items()
             if not (name.startswith("_") or name == 'ngettext')
-            if not inspect.ismodule(value)
+            if not isinstance(
+                value,
+                (types.ModuleType, types.LazyImportType),
+            )
         ]
         self.assertEqual(sorted(items), sorted(argparse.__all__))
 
diff --git 
a/Misc/NEWS.d/next/Library/2026-07-24-17-02-46.gh-issue-154638.7YnFHH.rst 
b/Misc/NEWS.d/next/Library/2026-07-24-17-02-46.gh-issue-154638.7YnFHH.rst
new file mode 100644
index 00000000000000..91c22640deba6b
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-07-24-17-02-46.gh-issue-154638.7YnFHH.rst
@@ -0,0 +1 @@
+Improve import time of :mod:`argparse` by lazily importing several 
dependencies.

_______________________________________________
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