Support lazy importing submodules in attach - #168
Conversation
Signed-off-by: Samuel Monson <smonson@redhat.com>
Signed-off-by: Samuel Monson <smonson@redhat.com>
Signed-off-by: Samuel Monson <smonson@redhat.com>
## TODO - [ ] ~Pending upstream change: scientific-python/lazy-loader#168 upstream seems dead so the module has been pulled in-house. - [ ] ~Support for soft extras (E.g. `perf` group)~ deferred - [ ] ~Lazy load in `__main__.py` to improve CLI responsiveness~ deferred - [ ] Docs cleanup (howto create a lazy module, do's and don'ts) - [ ] Actually test vLLM python (loading of vLLM tested but not a full run) ## Summary Lazy loads extras submodules in order to defer import errors to the time of use. ## Details TODO ## Test Plan Without vLLM: 1. Run `guidellm benchmark run --help` and observe no errors 2. Run `uv run guidellm benchmark run --backend vllm_python --model test` and observe error with helpful message With vLLM: 1. Run `guidellm benchmark run --help` and observe no errors 2. Run `uv run guidellm benchmark run --backend vllm_python --model test ...` and observe successful benchmark 3. Run `tox -re test-e2e` and observe that tests pass (Previously they would fail when vLLM was installed due to load times) ## Related Issues - Replaces #636 --- - [x] "I certify that all code in this PR is my own, except as noted below." ## Use of AI - [x] Includes AI-assisted code completion - [ ] Includes code generated by an AI application - [ ] Includes AI-generated tests (NOTE: AI written tests should have a docstring that includes `## WRITTEN BY AI ##`) --- # git log commit 19d8aad Author: Samuel Monson <smonson@redhat.com> Date: Tue May 19 17:49:25 2026 -0400 Pull in custom lazy_load package as submodule Signed-off-by: Samuel Monson <smonson@redhat.com> commit de50d31 Author: Samuel Monson <smonson@redhat.com> Date: Mon Jun 1 19:50:10 2026 -0400 Minor type fix Signed-off-by: Samuel Monson <smonson@redhat.com> commit 6066364 Author: Samuel Monson <smonson@redhat.com> Date: Tue Mar 17 16:33:04 2026 -0400 Switch to lazy-loading for extras packages Signed-off-by: Samuel Monson <smonson@redhat.com> commit 591a160 Author: Samuel Monson <smonson@redhat.com> Date: Wed Mar 18 16:58:33 2026 -0400 Use AttributeError for failed optionals `torch` seems to break when it encounters lazy ImportErrors Signed-off-by: Samuel Monson <smonson@redhat.com> commit 79bcd7d Author: Samuel Monson <smonson@redhat.com> Date: Wed May 20 17:42:54 2026 -0400 LazyModule which loads module attributes individually Generated-by: claude-code Sonnet 4.6 Signed-off-by: Samuel Monson <smonson@redhat.com> commit 812acf6 Author: Samuel Monson <smonson@redhat.com> Date: Wed May 20 17:50:37 2026 -0400 Fix unit tests Generated-by: claude-code Sonnet 4.6 Signed-off-by: Samuel Monson <smonson@redhat.com> commit 5a81cc2 Author: Samuel Monson <smonson@redhat.com> Date: Thu May 21 10:50:04 2026 -0400 Revert "LazyModule which loads module attributes individually" This reverts commit e31862e. Signed-off-by: Samuel Monson <smonson@redhat.com> commit 8a00c01 Author: Samuel Monson <smonson@redhat.com> Date: Mon Jun 1 20:05:32 2026 +0000 Split lazy loading from functionality Generated-by: claude-code Sonnet 4.6 Signed-off-by: Samuel Monson <smonson@redhat.com> commit b309ac4 Author: Samuel Monson <smonson@redhat.com> Date: Mon Jun 1 21:08:01 2026 +0000 Cleanup tests after split Generated-by: claude-code Sonnet 4.6 Signed-off-by: Samuel Monson <smonson@redhat.com> commit 7106bf8 Author: Samuel Monson <smonson@redhat.com> Date: Mon Jun 1 22:35:47 2026 +0000 Implement nested lazy loading Generated-by: claude-code Opus 4.6 Signed-off-by: Samuel Monson <smonson@redhat.com> commit fccdcd7 Author: Samuel Monson <smonson@redhat.com> Date: Tue Jun 2 00:09:19 2026 +0000 Switch attribute interface to a named tuple Generated-by: claude-code Opus 4.6 Signed-off-by: Samuel Monson <smonson@redhat.com> commit 7dea6a0 Author: Samuel Monson <smonson@redhat.com> Date: Tue Jun 2 00:47:11 2026 +0000 Add type stubs Generated-by: claude-code Opus 4.6 Signed-off-by: Samuel Monson <smonson@redhat.com> --------- Generated-by: claude-code Opus 4.6 Generated-by: claude-code Sonnet 4.6 Signed-off-by: Samuel Monson <smonson@redhat.com>
## TODO - [ ] ~Pending upstream change: scientific-python/lazy-loader#168 upstream seems dead so the module has been pulled in-house. - [ ] ~Support for soft extras (E.g. `perf` group)~ deferred - [ ] ~Lazy load in `__main__.py` to improve CLI responsiveness~ deferred - [ ] Docs cleanup (howto create a lazy module, do's and don'ts) - [ ] Actually test vLLM python (loading of vLLM tested but not a full run) ## Summary Lazy loads extras submodules in order to defer import errors to the time of use. ## Details TODO ## Test Plan Without vLLM: 1. Run `guidellm benchmark run --help` and observe no errors 2. Run `uv run guidellm benchmark run --backend vllm_python --model test` and observe error with helpful message With vLLM: 1. Run `guidellm benchmark run --help` and observe no errors 2. Run `uv run guidellm benchmark run --backend vllm_python --model test ...` and observe successful benchmark 3. Run `tox -re test-e2e` and observe that tests pass (Previously they would fail when vLLM was installed due to load times) ## Related Issues - Replaces vllm-project#636 --- - [x] "I certify that all code in this PR is my own, except as noted below." ## Use of AI - [x] Includes AI-assisted code completion - [ ] Includes code generated by an AI application - [ ] Includes AI-generated tests (NOTE: AI written tests should have a docstring that includes `## WRITTEN BY AI ##`) --- # git log commit 19d8aad Author: Samuel Monson <smonson@redhat.com> Date: Tue May 19 17:49:25 2026 -0400 Pull in custom lazy_load package as submodule Signed-off-by: Samuel Monson <smonson@redhat.com> commit de50d31 Author: Samuel Monson <smonson@redhat.com> Date: Mon Jun 1 19:50:10 2026 -0400 Minor type fix Signed-off-by: Samuel Monson <smonson@redhat.com> commit 6066364 Author: Samuel Monson <smonson@redhat.com> Date: Tue Mar 17 16:33:04 2026 -0400 Switch to lazy-loading for extras packages Signed-off-by: Samuel Monson <smonson@redhat.com> commit 591a160 Author: Samuel Monson <smonson@redhat.com> Date: Wed Mar 18 16:58:33 2026 -0400 Use AttributeError for failed optionals `torch` seems to break when it encounters lazy ImportErrors Signed-off-by: Samuel Monson <smonson@redhat.com> commit 79bcd7d Author: Samuel Monson <smonson@redhat.com> Date: Wed May 20 17:42:54 2026 -0400 LazyModule which loads module attributes individually Generated-by: claude-code Sonnet 4.6 Signed-off-by: Samuel Monson <smonson@redhat.com> commit 812acf6 Author: Samuel Monson <smonson@redhat.com> Date: Wed May 20 17:50:37 2026 -0400 Fix unit tests Generated-by: claude-code Sonnet 4.6 Signed-off-by: Samuel Monson <smonson@redhat.com> commit 5a81cc2 Author: Samuel Monson <smonson@redhat.com> Date: Thu May 21 10:50:04 2026 -0400 Revert "LazyModule which loads module attributes individually" This reverts commit e31862e. Signed-off-by: Samuel Monson <smonson@redhat.com> commit 8a00c01 Author: Samuel Monson <smonson@redhat.com> Date: Mon Jun 1 20:05:32 2026 +0000 Split lazy loading from functionality Generated-by: claude-code Sonnet 4.6 Signed-off-by: Samuel Monson <smonson@redhat.com> commit b309ac4 Author: Samuel Monson <smonson@redhat.com> Date: Mon Jun 1 21:08:01 2026 +0000 Cleanup tests after split Generated-by: claude-code Sonnet 4.6 Signed-off-by: Samuel Monson <smonson@redhat.com> commit 7106bf8 Author: Samuel Monson <smonson@redhat.com> Date: Mon Jun 1 22:35:47 2026 +0000 Implement nested lazy loading Generated-by: claude-code Opus 4.6 Signed-off-by: Samuel Monson <smonson@redhat.com> commit fccdcd7 Author: Samuel Monson <smonson@redhat.com> Date: Tue Jun 2 00:09:19 2026 +0000 Switch attribute interface to a named tuple Generated-by: claude-code Opus 4.6 Signed-off-by: Samuel Monson <smonson@redhat.com> commit 7dea6a0 Author: Samuel Monson <smonson@redhat.com> Date: Tue Jun 2 00:47:11 2026 +0000 Add type stubs Generated-by: claude-code Opus 4.6 Signed-off-by: Samuel Monson <smonson@redhat.com> --------- Generated-by: claude-code Opus 4.6 Generated-by: claude-code Sonnet 4.6 Signed-off-by: Samuel Monson <smonson@redhat.com> Signed-off-by: SkiHatDuckie <SkiHatDuckie@gmail.com>
|
Thanks for the contribution @sjmonson. I don't see a test that exercises the new behavior? |
|
@stefanv Oh sorry I forgot about this PR. It actually turned out that while this idea worked in theory, in practice it is pretty fragile and packages like PyTorch can break it by trying to walk I ended up solving this problem a different way by making a new version of |
|
Thanks for the update, Samuel! Can you explain a bit about what https://github.com/vllm-project/guidellm/blob/d07502b51b4c30d7acdc17ee8990c3899978cb08/src/guidellm/utils/lazy_loader.py#L163 does? |
|
Sure, basically the goal is to bring a series of imports in a attributes on the current module without importing the source module in advance. Since we don't know if each attribute we are importing is a attribute of the source module or a submodule of the source module we need to try a couple different things. src/guidellm/extras/vision.py is a good example. We essentially want a module that looks like: import imageio.v3 as iio
from PIL import Image as PILImage
from PIL.Image import Image
__all__ = ["Image", "PILImage", "iio"]
At the start of |
Adds a
lazy_submodules: boolargument toattachwhich substitutesimportlib.import_modulefor theloadfunction. Found this useful for bundling a bunch of functions/objects with their required extras. E.g.pkg/extras/__init__.pypkg/extras/group_one.py