]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-132737: Support profiling modules that require __main___ (#132738)
authorAneesh Durg <aneeshdurg17@gmail.com>
Thu, 24 Apr 2025 18:41:01 +0000 (13:41 -0500)
committerGitHub <noreply@github.com>
Thu, 24 Apr 2025 18:41:01 +0000 (14:41 -0400)
Lib/cProfile.py
Lib/test/test_cprofile.py
Misc/NEWS.d/next/Core_and_Builtins/2025-04-19-18-07-34.gh-issue-132737.9mW1il.rst [new file with mode: 0644]

index e7c868b8d555438cdb5a24e8b70158a3de17b7ec..770d26f79628fe14aa735cfe0258a84f912d5bea 100644 (file)
@@ -6,6 +6,7 @@ __all__ = ["run", "runctx", "Profile"]
 
 import _lsprof
 import importlib.machinery
+import importlib.util
 import io
 import profile as _pyprofile
 
@@ -173,13 +174,22 @@ def main():
                 code = compile(fp.read(), progname, 'exec')
             spec = importlib.machinery.ModuleSpec(name='__main__', loader=None,
                                                   origin=progname)
-            globs = {
+            module = importlib.util.module_from_spec(spec)
+            # Set __main__ so that importing __main__ in the profiled code will
+            # return the same namespace that the code is executing under.
+            sys.modules['__main__'] = module
+            # Ensure that we're using the same __dict__ instance as the module
+            # for the global variables so that updates to globals are reflected
+            # in the module's namespace.
+            globs = module.__dict__
+            globs.update({
                 '__spec__': spec,
                 '__file__': spec.origin,
                 '__name__': spec.name,
                 '__package__': None,
                 '__cached__': None,
-            }
+            })
+
         try:
             runctx(code, globs, None, options.outfile, options.sort)
         except BrokenPipeError as exc:
index b46edf66bf09f8ae4d71a26112cf17cf1d66f3dc..192c8eab26ebff3a505b98e2c5ca7f1cc2926a79 100644 (file)
@@ -5,8 +5,10 @@ import unittest
 
 # rip off all interesting stuff from test_profile
 import cProfile
+import tempfile
+import textwrap
 from test.test_profile import ProfileTest, regenerate_expected_output
-from test.support.script_helper import assert_python_failure
+from test.support.script_helper import assert_python_failure, assert_python_ok
 from test import support
 
 
@@ -154,6 +156,19 @@ class TestCommandLine(unittest.TestCase):
         self.assertGreater(rc, 0)
         self.assertIn(b"option -s: invalid choice: 'demo'", err)
 
+    def test_profile_script_importing_main(self):
+        """Check that scripts that reference __main__ see their own namespace
+        when being profiled."""
+        with tempfile.NamedTemporaryFile("w+", delete_on_close=False) as f:
+            f.write(textwrap.dedent("""\
+                class Foo:
+                    pass
+                import __main__
+                assert Foo == __main__.Foo
+                """))
+            f.close()
+            assert_python_ok('-m', "cProfile", f.name)
+
 
 def main():
     if '-r' not in sys.argv:
diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-04-19-18-07-34.gh-issue-132737.9mW1il.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-04-19-18-07-34.gh-issue-132737.9mW1il.rst
new file mode 100644 (file)
index 0000000..0f01091
--- /dev/null
@@ -0,0 +1 @@
+Support profiling code that requires ``__main__``, such as :mod:`pickle`.