https://github.com/python/cpython/commit/fd252e80f5a1a40eb8ed05ea47a36c33f8eec760
commit: fd252e80f5a1a40eb8ed05ea47a36c33f8eec760
branch: 3.15
author: Miss Islington (bot) <[email protected]>
committer: pablogsal <[email protected]>
date: 2026-06-08T23:04:06+01:00
summary:

[3.15] gh-148932: Fix `profiling.sampling` on Windows virtual environments 
(GH-150541) (#151097)

gh-148932: Fix `profiling.sampling` on Windows virtual environments (GH-150541)
(cherry picked from commit 5c1321731403031d933ca469977e4bb3859c8680)

Co-authored-by: Eduardo Villalpando Mello <[email protected]>

files:
A Misc/NEWS.d/next/Library/2026-05-27-23-47-31.gh-issue-148932.Y1xmvA.rst
M Doc/library/profiling.sampling.rst
M Lib/profiling/sampling/sample.py

diff --git a/Doc/library/profiling.sampling.rst 
b/Doc/library/profiling.sampling.rst
index 39b6ea4e31cde72..aeb1a429b58515a 100644
--- a/Doc/library/profiling.sampling.rst
+++ b/Doc/library/profiling.sampling.rst
@@ -387,11 +387,6 @@ This requires one of:
 On Windows, the profiler requires administrative privileges or the
 ``SeDebugPrivilege`` privilege to read another process's memory.
 
-*Note*: On Windows, ``python -m profiling.sampling`` fails inside a virtual
-environment because the venv's ``python.exe`` is just a launcher shim that
-re-executes the base interpreter as a child process. The shim itself isn't
-a Python process and has no ``PyRuntime`` section to attach to. Instead,
-run it from the global Python installation.
 
 Version compatibility
 ---------------------
diff --git a/Lib/profiling/sampling/sample.py b/Lib/profiling/sampling/sample.py
index 2d379e1e16a35e3..50ccc57566d70d3 100644
--- a/Lib/profiling/sampling/sample.py
+++ b/Lib/profiling/sampling/sample.py
@@ -50,9 +50,38 @@ def _pause_threads(unwinder, blocking):
 # Maximum number of consecutive identical samples to keep before flushing.
 MAX_PENDING_SAMPLES = 8192
 
+
+def _resolve_python_pid(pid):
+    """On Windows, if pid is a venvlauncher process, return the child Python 
PID.
+
+    The venvlauncher (used as python.exe in venvs) spawns the real Python
+    interpreter as a child process via CreateProcessW. The RemoteUnwinder
+    needs the child's PID, not the launcher's.
+
+    Returns the original pid if not on Windows, not a venv launcher,
+    or no child process is found.
+    """
+    if os.name != "nt" or sys.prefix == sys.base_prefix:
+        return pid
+    try:
+        children = _remote_debugging.get_child_pids(pid, recursive=False)
+        python_children = [
+            child for child in children
+            if _remote_debugging.is_python_process(child)
+        ]
+        if len(python_children) == 1:
+            return python_children[0]
+    except (OSError, RuntimeError) as err:
+        raise SystemExit(
+            f"Failed to initialize profiler from virtualenv: {err}\n"
+            f"Try running with the base interpreter: {sys._base_executable}"
+        ) from err
+    return pid
+
+
 class SampleProfiler:
     def __init__(self, pid, sample_interval_usec, all_threads, *, 
mode=PROFILING_MODE_WALL, native=False, gc=True, opcodes=False, 
skip_non_matching_threads=True, collect_stats=False, blocking=False):
-        self.pid = pid
+        self.pid = _resolve_python_pid(pid)
         self.sample_interval_usec = sample_interval_usec
         self.all_threads = all_threads
         self.mode = mode  # Store mode for later use
@@ -61,10 +90,6 @@ def __init__(self, pid, sample_interval_usec, all_threads, 
*, mode=PROFILING_MOD
         try:
             self.unwinder = self._new_unwinder(native, gc, opcodes, 
skip_non_matching_threads)
         except RuntimeError as err:
-            if os.name == "nt" and sys.executable.endswith("python.exe"):
-                raise SystemExit(
-                    "Running profiling.sampling from virtualenv on Windows 
platform is not supported"
-                ) from err
             raise SystemExit(err) from err
         # Track sample intervals and total sample count
         self.sample_intervals = deque(maxlen=100)
diff --git 
a/Misc/NEWS.d/next/Library/2026-05-27-23-47-31.gh-issue-148932.Y1xmvA.rst 
b/Misc/NEWS.d/next/Library/2026-05-27-23-47-31.gh-issue-148932.Y1xmvA.rst
new file mode 100644
index 000000000000000..a0b7a9740cd518d
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-05-27-23-47-31.gh-issue-148932.Y1xmvA.rst
@@ -0,0 +1 @@
+Fix ``profiling.sampling`` on Windows virtual environments to resolve the 
actual Python PID from a virtual environment shim.

_______________________________________________
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