Skip to content

Speed up import rlcompleter by deferring inspect and re #156363

Description

@maxday

rlcompleter imports inspect and re at module scope, but neither is needed to import the module or to construct a Completer. Each is used in exactly one completion method:

  • inspect: only in Completer._callable_postfix
  • re: only in Completer.attr_matches

inspect in particular is a heavy import: it transitively pulls in dis, tokenize, and more. Because rlcompleter is imported during interactive startup (to set up tab completion via readline), this import cost is paid on every interactive session and every import rlcompleter, even though the completion methods may never run.

Linked PRs

Activity

  1. maxday commented on Aug 25, 2026

    @maxday
    ContributorAuthor

    I'm working on this :)

  2. added 2 commits that reference this issue on Aug 25, 2026
  3. added
    performancePerformance or resource usage
    stdlibStandard Library Python modules in the Lib/ directory
    on Aug 25, 2026
  4. added 2 commits that reference this issue on Aug 25, 2026
  5. aisk commented on Aug 26, 2026

    @aisk
    Member

    One thing to notice, on the interactive startup path these two modules get imported a moment later anyway, since _pyrepl.readline is imported right after rlcompleter and pulls them both in:

    $ ./python -c "import sys, _pyrepl.readline; print('re' in sys.modules, 'inspect' in sys.modules)"
    True True

    So the gain doesn't really materialize for the interactive interpreter. It may still help people who use this module on its own, though.

  6. maxday commented on Aug 28, 2026

    @maxday
    ContributorAuthor

    You're right @aisk, on the default PyREPL path _pyrepl.readline pulls in both re (directly) and inspect (via dataclasses(slots=True) in _pyrepl/utils.py), so the deferral is neutral there.

    It does still help in two cases: PYTHON_BASIC_REPL=1, where site.py skips the _pyrepl.readline import entirely, and standalone use of rlcompleter (e.g. readline.set_completer(rlcompleter.Completer(ns).complete)), where importing the module drops from ~15 ms to ~1.6 ms and avoids ~35 transitive modules.

    It also helps people who use this module on its own indeed.

    Since it's neutral on the common path and a win on the others and in line with the ongoing startup-time / PEP 810 work, I think it's still worth doing, let me know!

  7. added a commit that references this issue on Sep 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    performancePerformance or resource usagestdlibStandard Library Python modules in the Lib/ directorytype-featureA feature request or enhancement

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions