GH-155009: Preserve argparse prog for programmatic module-as-main execution (#155199)

savannahostrowski <[email protected]> Wed, 05 Aug 2026 00:43:21 -0400 (EDT)
Newsgroups gmane.comp.python.cvs
Message-ID <[email protected]>
https://github.com/python/cpython/commit/ca4518b7f73bcd79d49ea20390f45827ddd0cb67
commit: ca4518b7f73bcd79d49ea20390f45827ddd0cb67
branch: main
author: Savannah Ostrowski <[email protected]>
committer: savannahostrowski <[email protected]>
date: 2026-08-05T04:43:08Z
summary:

GH-155009: Preserve argparse prog for programmatic module-as-main execution (#155199)

files:
A Misc/NEWS.d/next/Library/2026-08-05-02-36-18.gh-issue-155009.YiJAiP.rst
M Lib/argparse.py
M Lib/test/test_argparse.py

diff --git a/Lib/argparse.py b/Lib/argparse.py
index 0840c4c45cffaa..25994d7a389efa 100644
--- a/Lib/argparse.py
+++ b/Lib/argparse.py
@@ -1964,6 +1964,9 @@ def _prog_name(prog=None):
     if modspec is None:
         # simple script
         return _os.path.basename(arg0)
+    if modspec.name != '__main__' and arg0 != modspec.origin:
+        # named module executed as main without altering sys.argv[0]
+        return _os.path.basename(arg0)
     py = _os.path.basename(_sys.executable)
     if modspec.name != '__main__':
         # imported module or package
diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py
index 287fcb7a084a49..ae02cd11804e50 100644
--- a/Lib/test/test_argparse.py
+++ b/Lib/test/test_argparse.py
@@ -7346,6 +7346,19 @@ def test_module(self, compiled=False):
     def test_module_compiled(self):
         self.test_module(compiled=True)
 
+    def test_module_as_main_without_altering_argv(self):
+        basename = 'module' + os_helper.FS_NONASCII
+        modulename = f'{self.dirname}.{basename}'
+        self.make_script(self.dirname, basename)
+        runner_source = textwrap.dedent(f'''\
+            import runpy
+            runpy._run_module_as_main({modulename!r}, alter_argv=False)
+        ''')
+        runner = script_helper.make_script(
+            self.dirname, 'runner', runner_source)
+        self.check_usage(os.path.basename(runner), runner,
+                         PYTHONPATH=os.curdir)
+
     def test_package(self, compiled=False):
         basename = 'subpackage' + os_helper.FS_NONASCII
         packagename = f'{self.dirname}.{basename}'
diff --git a/Misc/NEWS.d/next/Library/2026-08-05-02-36-18.gh-issue-155009.YiJAiP.rst b/Misc/NEWS.d/next/Library/2026-08-05-02-36-18.gh-issue-155009.YiJAiP.rst
new file mode 100644
index 00000000000000..219c6a94b91cb6
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-08-05-02-36-18.gh-issue-155009.YiJAiP.rst
@@ -0,0 +1,3 @@
+Fix :class:`argparse.ArgumentParser` to preserve the program name from
+``sys.argv[0]`` when a named module is executed as the main program without
+replacing ``sys.argv[0]``.

_______________________________________________
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]