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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions