summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAneesh Durg <aneeshdurg17@gmail.com>2025-04-24 18:41:01 (GMT)
committerGitHub <noreply@github.com>2025-04-24 18:41:01 (GMT)
commitc7a7aa9a57c25ef2666f7dbf62edab882747af6b (patch)
tree9758b57d19fba1afad204b244eb5c0154996bd7c
parente1c09fff054ebcb90e72bba25ef7332bcabec92b (diff)
downloadcpython-c7a7aa9a57c25ef2666f7dbf62edab882747af6b.zip
cpython-c7a7aa9a57c25ef2666f7dbf62edab882747af6b.tar.gz
cpython-c7a7aa9a57c25ef2666f7dbf62edab882747af6b.tar.bz2
gh-132737: Support profiling modules that require __main___ (#132738)
-rw-r--r--Lib/cProfile.py14
-rw-r--r--Lib/test/test_cprofile.py17
-rw-r--r--Misc/NEWS.d/next/Core_and_Builtins/2025-04-19-18-07-34.gh-issue-132737.9mW1il.rst1
3 files changed, 29 insertions, 3 deletions
diff --git a/Lib/cProfile.py b/Lib/cProfile.py
index e7c868b..770d26f 100644
--- a/Lib/cProfile.py
+++ b/Lib/cProfile.py
@@ -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:
diff --git a/Lib/test/test_cprofile.py b/Lib/test/test_cprofile.py
index b46edf6..192c8ea 100644
--- a/Lib/test/test_cprofile.py
+++ b/Lib/test/test_cprofile.py
@@ -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
index 0000000..0f01091
--- /dev/null
+++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-04-19-18-07-34.gh-issue-132737.9mW1il.rst
@@ -0,0 +1 @@
+Support profiling code that requires ``__main__``, such as :mod:`pickle`.