Skip to content

Nested subprocess python -m ... fails module resolution only when parent is launched via debugpy #2002

@michaeltufar

Description

@michaeltufar

Summary

In a Windows project with src/ layout, a parent Python module runs correctly under debugpy, but a child subprocess started from that parent with:

python -m my_tools.tasks.validation.main

fails with:

No module named my_tools.tasks.validation.main

The exact same child command succeeds outside debugpy (normal terminal/task run).


Environment

  • OS: Windows (PowerShell)
  • Python: virtualenv interpreter (.venv\Scripts\python.exe), debugpy 1.8.19
  • VS Code Python extension (debugpy launcher used by VS Code)
  • Project layout: src/my_tools/...
  • PYTHONPATH in launch config: <workspace>/src

Expected behavior

If parent process is launched via debugpy and parent starts child with:

<venv_python> -m my_tools.tasks.validation.main ...

then child should resolve and execute module exactly as in terminal mode.


Actual behavior

When parent is launched via debugpy (module launch in launch.json), child subprocess fails:

No module named my_tools.tasks.validation.main

When parent is launched normally (no debugpy), same child command succeeds.


Reproduction pattern

Parent debug launch (fails in child)

VS Code launch command shape:

<venv>\python.exe <...>\debugpy\launcher <port> -- -m my_tools.service.runner.main ...

Inside parent:

cmd = [
    sys.executable,
    "-m",
    "my_tools.tasks.validation.main",
    "--help",
]
subprocess.run(
    cmd,
    cwd="<workspace>",
    env=env_with_pythonpath,
    capture_output=True,
    text=True,
)

Result under debug launch:

stderr: No module named my_tools.tasks.validation.main

Parent non-debug launch (works)

python -m my_tools.service.runner.main ...

Result: child module resolves and completes successfully.

Manual debugpy CLI launch (also fails)

After installing debugpy into the same venv, launching parent via CLI debugpy reproduces the same child failure:

python -m debugpy --listen 5678 -m my_tools.service.runner.main --queue-root <...> --work-root <...> --once --log-level DEBUG

Result:

stderr: No module named my_tools.tasks.validation.main

Sanity checks already done

All of the following succeed in same venv:

python -c "import os,sys,importlib.util as u,my_tools; print(sys.executable); print(os.getenv('PYTHONPATH')); print(u.find_spec('my_tools.tasks.validation.main'))"

find_spec(...) returns valid ModuleSpec under <workspace>/src/my_tools/....

Also succeeds:

python -c "import os,sys,subprocess; env=os.environ.copy(); env['PYTHONPATH']=r'<workspace>\\src;<workspace>/src'; cmd=[sys.executable,'-m','my_tools.tasks.validation.main','--help']; r=subprocess.run(cmd,cwd=r'<workspace>',env=env,capture_output=True,text=True); print(r.returncode); print(r.stderr)"

Return code is 0, stderr empty.


Why this looks debugpy-related

  • Same interpreter path.
  • Same module path.
  • Same child command works outside debugpy.
  • Failure appears when parent is launched via debugpy (VS Code launcher and manual python -m debugpy).
  • The failing point is nested child module resolution via -m.

Current workaround

  • Run parent as normal task/terminal (non-debug) for production-like execution.
  • Alternative code workaround: launch child by script path instead of -m, e.g.:
python <workspace>/src/my_tools/tasks/validation/main.py ...

Question to maintainers

Is this a known issue/limitation with:

  • debugpy launcher + nested subprocess -m calls
  • src/ layout + PYTHONPATH
  • Windows-specific env/path propagation

and is there a recommended debugpy setting to make nested child -m module resolution deterministic?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions