Improve import startup with lazy top-level exports#2950
Improve import startup with lazy top-level exports#2950fede-kamel wants to merge 4 commits intoopenai:mainfrom
Conversation
|
Validation summary for #2819:
Interpretation: default lazy mode reduces import startup work significantly; eager mode remains available for CI/dev verification. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2bd0b97246
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
Two things, about the env var for eager load
I think it's great you're working on a fix for this btw... thank you |
|
Took this feedback and removed the runtime eager-import env var path from The branch now keeps lazy imports as the only product behavior and makes the coverage explicit in tests instead:
Validated locally with:
|
|
@RobertCraigie @rachellim @g0t4 — Friendly ping! Just re-validated the branch: all tests pass ( |
The 2.32.0 release added 'from .types.websocket_reconnection import ...' at the top of openai/__init__.py, which transitively loads openai.types through openai._client as well. That invalidates the 'openai.types is lazy' assertion the earlier test relied on, so the lazy-types live test is removed and the remaining tests assert the boundaries that still hold (lib.azure, lib.streaming, lib._tools). Also stabilize pyright under strict: - preserve static visibility of AzureOpenAI / AsyncAzureOpenAI / pydantic_function_tool / AssistantEventHandler under TYPE_CHECKING so callers keep their signatures - rename _AZURE_MODULE_CLIENT_CLASS to a non-constant symbol and type the module-client factory as type[AzureOpenAI] to silence strict reportCallIssue / reportConstantRedefinition warnings - tidy ruff imports / I001 noise in scripts/bench_import.py and the test files added in this branch
2cb445c to
b0fb0f4
Compare
|
Friendly bump for maintainer review — rebased onto What changed since last review
Integration benchmark (Python 3.13, cold
|
| metric | origin/main (2.32.0) |
this branch | speedup |
|---|---|---|---|
| min | 346 ms | 288 ms | 1.20× |
| median | 401 ms | 325 ms | 1.23× |
| mean | 397 ms | 338 ms | 1.18× |
Python's own -X importtime cumulative time for the openai module:
origin/main: 390 ms- this branch: 232 ms → 1.68× faster / ~158 ms shaved
Repro: python scripts/bench_import.py (also in the branch).
What still stays lazy after the rebase
Verified on import openai:
openai.lib.azure— not loadedopenai.lib.streaming— not loadedopenai.lib._tools— not loaded
These are the biggest non-transitively-required submodules, which is where the ~160 ms comes from.
Happy to split further or squash to the original 3 commits if preferred. Would love to get this in — the import-time win is meaningful for CLI / Lambda / short-lived workers.
|
@mcgrew-oai @hintz-openai — friendly ping in case this slipped off the review queue. Just rebased onto 2.32.0 (see benchmark comment above: ~1.18–1.23× faster cold |
Summary
This PR addresses import-time startup regression tracked in #2819 by making heavy top-level exports lazy.
Key changes:
openai.__init__for:AzureOpenAIAsyncAzureOpenAIpydantic_function_toolAssistantEventHandlerAsyncAssistantEventHandlerOPENAI_EAGER_IMPORT=1scripts/bench_import.py.tests/test_import_surface.pytests/lib/test_import_surface_live.py(live-gated)Why this relates to #2819
Issue #2819 reports that
import openaiis too slow and that eager loading of type-heavy/internal surfaces is a major contributor. This PR reduces startup cost in the default path by moving expensive imports behind first-use access while preserving API compatibility.Testing done
Unit / behavior tests
PYTHONPATH=src python3 -m pytest tests/test_import_surface.py -q -o addopts=''-> passedPYTHONPATH=src python3 -m pytest tests/test_module_client.py -q -o addopts=''-> passedLive API-key integration test
OPENAI_LIVE=1 PYTHONPATH=src OPENAI_API_KEY=... python3 -m pytest tests/lib/test_import_surface_live.py -q -o addopts=''-> passedclient.models.list()).Performance benchmarks
Using
scripts/bench_import.py:0.1533sOPENAI_EAGER_IMPORT=1):0.2601s+0.1068s(+69.7%)0.7019s2.9429s+2.2410s(+319.3%)Interpretation: eager mode is intentionally slower, and the default lazy path materially reduces startup work compared with forced eager loading.
Notes
OPENAI_LIVE=1andOPENAI_API_KEY.