Skip to content

FIX: kernprof to always run code in sys.modules['__main__']'s namespace#423

Open
TTsangSC wants to merge 4 commits intopyutils:mainfrom
TTsangSC:profile-subprocesses
Open

FIX: kernprof to always run code in sys.modules['__main__']'s namespace#423
TTsangSC wants to merge 4 commits intopyutils:mainfrom
TTsangSC:profile-subprocesses

Conversation

@TTsangSC
Copy link
Collaborator

@TTsangSC TTsangSC commented Mar 5, 2026

Motivation

As discussed in #422, depending on the invocation of kernprof, the profiled/executed code was not always consistently executed in sys.modules['__main__']'s namespace. This poses issues with e.g. code using multiprocessing: the executed functions and data are pickled, and that in turn relies on their being reachable and retrievable via their expected locations in sys.modules.

Code changes

Monkey-patching sys.modules['__main__'] with an appropriate dummy module object makes sure that the executed code is run in the context and namespace of __main__. This is currently only done for line_profiler.autoprofile.autoprofile.run(..., as_module=True), which is only used when kernprof is called with line-profiling active (-l), with profiling targets supplied (-p <...>), and executing the code as a module (-m)).

The following functions are now updated so that all code paths kernprof takes would receive the same treatment:

  • line_profiler.autoprofile.autoprofile.run()
  • kernprof._main_profile()

Test changes

A new test module tests/test_child_procs.py is now added, extending upon the failing case in #422 to make sure that kernprof can now handle such the execution of such code:

  • test_module
    pytest fixture of a file containing test code using multiprocessing to parallelize some workload across child processes; can be run either as a script or a module, with customizable workload and parallelization
  • test_multiproc_script_sanity_check()
    Checking that the test code works as expected when run with vanilla Python
  • test_running_multiproc_script(), test_running_multiproc_module()
    Checking that the execution of the test code is not affected by kernprof in all code paths

This test module is expected to be extended with tests where the actual profiling of child processes is tested (when we get there; maybe I can just chuck a couple in there which XFAIL at the moment?).

Other changes

In CHANGELOG.md:

  • Added entry
  • Fixed version-number typo in a header (5.0.1 -> 5.0.2)

Caveats

We can't currently properly profile child Python processes anyway; still, it is worthwhile to work towards that, and failing that, at the very least fix the bug so that the kernprof doesn't choke on random code.

TTsangSC added 4 commits March 5, 2026 01:51
line_profiler/autoprofile/autoprofile.py::run()
    - Now always creating a temporary module object for
      `sys.modules['__main__']` (not only when `as_module=True`),
      executing the code in its namespace and context
    - Simplified internal code and dropped some imports due to the
      reduced branching
kernprof.py::_main_profile()
    As with `line_profiler.autoprofile.autoprofile.run()`, the code
    execution now always happens in the namespace of a temporary module
    object at `sys.modules['__main__']`;
    this now covers cases without with `--prof-mod=...` and/or
    `--line-by-line` flags
tests/test_child_procs.py
    New test module (to be expanded) checking that `kernprof` doesn't
    choke when running code using `multiprocessing`

    - test_module
      `pytest` fixture for a script/module, in which a function is
      called parallel-ly with `multiprocessing.Pool.map()`
    - test_multiproc_script_sanity_check()
      Test that the test code works as intended with vanilla Python
    - test_running_multiproc_{script,module}()
      Test that the test code works as intended with `kernprof`, both
      when invoked as a module and a script

    TODO:

    - XFailed tests for incomplete profiling results
    - Actual implementation of child-process profiling
@codecov
Copy link

codecov bot commented Mar 5, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 89.02%. Comparing base (60e928f) to head (1120c7f).
⚠️ Report is 33 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #423      +/-   ##
==========================================
+ Coverage   87.56%   89.02%   +1.45%     
==========================================
  Files          18       20       +2     
  Lines        1641     2250     +609     
  Branches      348      473     +125     
==========================================
+ Hits         1437     2003     +566     
- Misses        149      184      +35     
- Partials       55       63       +8     
Files with missing lines Coverage Δ
line_profiler/autoprofile/autoprofile.py 97.72% <100.00%> (-2.28%) ⬇️

... and 4 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 8929fcd...1120c7f. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant