You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Confirm this is an issue with the Python library and not an underlying OpenAI API
This is an issue with the Python library
Describe the bug
On average, it takes a long time to run import openai on recent hardware and software.
Average of 2 seconds on:
Windows 11 with
Intel(R) Core(TM) Ultra 7 165H (3.80 GHz)
32.0 GB (31.6 GB usable)
Average of 0.7 seconds on:
Ubuntu 24.04 HP Z420 workstation
Intel Xeon E5-1650 v2 x 12
64.0 Gib
If that sounds normal, consider the case where a bunch of deps are imported and each one of them takes 2 seconds to be imported. For example, I discovered this issue when trying to use Microsoft's Agentic Framework and Semantic Kernel libraries. Both of those routinely take over 30 seconds to import, spending most of that time importing openai. This renders the libraries useless for CLI or dev utilities and limits them to long-running applications.
This is a near-duplicate of Slow import times #2339, which was fixed, but has reappeared. It seems the new slowdown is caused by expansive internal typing libraries. These can be helpful for developing but are likely irrelevant to the consumer. f
Seeing similar things here. We use pyleak to detect event loop blocking in our app and our CI started failing recently, with the stacktrace pointing towards importlib when trying to import openai.
The slowdown comes from the openai.types package being imported unconditionally. Those modules pull in a lot of typing information that isn't needed at runtime.
A few practical ways to reduce the import time:
Guard the heavy typing imports with if TYPE_CHECKING: so they are only evaluated by type‑checkers.
Move the typing definitions to a separate module (e.g. openai._types) and import it lazily when typing.get_type_hints is called.
Expose a minimal entry point that avoids loading openai.types by default, e.g. from openai import OpenAI which only brings in the client class.
Provide an environment variable such as OPENAI_SKIP_TYPES=1 that the package checks and skips the typing import path.
Use importlib to defer loading of sub‑modules until they are actually accessed.
These changes keep the public API stable while shaving seconds off the initial import.
If you want to see the monetary impact of each LLM call in your application, focxle prints what each agent costs you across vendors. It is free to try, needs no account, and adds only two lines of code.
I profiled this on openai 3.3.1 / Python 3.13 to find where the time actually goes. openai.types is the right suspect, but the specific cause is narrower and more fixable than it looks.
Breakdown of a cold import openai (450 ms of import time, 1099 modules):
bucket
self ms
share
modules
openai.types.* (non-beta)
143.9
32.0%
434
openai.types.beta.*
137.2
30.5%
318
stdlib / other
91.0
20.3%
188
pydantic*
31.5
7.0%
43
http stack
21.6
4.8%
63
openai core
20.1
4.5%
42
openai.lib.*
3.9
0.9%
11
The openai.types.beta.* row is the interesting one: 30% of every import openai, for the Assistants API, paid by everyone who never touches it. It is not pulled in by openai/types/__init__.py — that file has no beta reference. The chain is:
openai/__init__.py:111 from .lib.streaming import AssistantEventHandler, ...
-> openai/lib/streaming/_assistants.py:13-24
from ...types.beta import AssistantStreamEvent
from ...types.beta.threads import Run, Text, Message, ...
from ...types.beta.threads.runs import RunStep, ToolCall, ...
_assistants.py already has from __future__ import annotations, so all but two of those names are only needed by type checkers. The exceptions are RunStep (construct_type(type_=RunStep, ...) in accumulate_run_step) and MessageContent (twice in accumulate_event), both inside function bodies.
Moving the imports under TYPE_CHECKING and importing those two locally gets, measured from a clean checkout with the repo's own venv, 25 cold runs each:
sys.modules
openai.types.beta
wall, median
main
1234
318
359.2 ms
patched
916
0
256.7 ms
1.40x, −102 ms, −318 modules. openai.AssistantEventHandler and openai.AsyncAssistantEventHandler stay eagerly exported, so there is no public API change and no module-level __getattr__.
This also explains why #2950 landed at only ~4%: it deferred openai.lib itself, which is the 0.9% row. The cost was never in lib — it was in what one lib module dragged behind it.
Worth noting for the generated-code concern that sank that PR: the entire change is in src/openai/lib/streaming/_assistants.py, which CONTRIBUTING.md says the generator never modifies, and which carries no File generated from our OpenAPI spec header. So it is outside the Castiron custom-code budget and cannot conflict with a regen.
Opened as #3727. ./scripts/lint is clean (ruff, pyright strict, mypy) and ./scripts/test passes both lanes (9127 on Pydantic v2, 9113 on v1), with a regression test that fails on main.
The remaining non-beta openai.types.* cost (~144 ms, 434 modules) is imported from openai/__init__.py directly, so shifting that one does need a change to generated code.
(Profiling done with importcost, which I wrote — importcost profile "import openai" reproduces the first table.)
Thanks for reporting this and sharing the profiling details! We shipped an upstream fix in #3898, available in v3.16.1, that avoids loading unused resources and Assistants types during startup. Closing this for now—please try the latest release and let me know if imports are still causing problems in your setup.
Activity
TheCoreMan commentedon Jan 15, 2026
Seeing similar things here. We use pyleak to detect event loop blocking in our app and our CI started failing recently, with the stacktrace pointing towards importlib when trying to import openai.
g0t4 commentedon Feb 27, 2026
is there a way to flag this as perfect for Codex to fix ?
IIAC this can use LazyProxy (or something similar with getattr/TYPE_CHECKING magic)?
fede-kamel commentedon Mar 10, 2026
Hi @jmathes — I opened a PR with a targeted lazy-import fix for this issue: #2950
What I changed:
openai.__init__lazy (AzureOpenAI,AsyncAzureOpenAI,pydantic_function_tool, assistant handlers)OPENAI_EAGER_IMPORT=1mode to force eager resolution in CI/devKey results from testing:
0.1533svs eager0.2601s(+69.7%)0.7019svs eager2.9429s(+319.3%)OPENAI_LIVE=1, realclient.models.list()call)PR includes full details and test commands: #2950
khalidsaidi commentedon Mar 25, 2026
A2ABench has an accepted answer for this imported thread.
ai villagemragnii commentedon Aug 18, 2026
The slowdown comes from the
openai.typespackage being imported unconditionally. Those modules pull in a lot of typing information that isn't needed at runtime.A few practical ways to reduce the import time:
if TYPE_CHECKING:so they are only evaluated by type‑checkers.openai._types) and import it lazily whentyping.get_type_hintsis called.openai.typesby default, e.g.from openai import OpenAIwhich only brings in the client class.OPENAI_SKIP_TYPES=1that the package checks and skips the typing import path.importlibto defer loading of sub‑modules until they are actually accessed.These changes keep the public API stable while shaving seconds off the initial import.
If you want to see the monetary impact of each LLM call in your application, focxle prints what each agent costs you across vendors. It is free to try, needs no account, and adds only two lines of code.
aviseth commentedon Aug 24, 2026
I profiled this on
openai3.3.1 / Python 3.13 to find where the time actually goes.openai.typesis the right suspect, but the specific cause is narrower and more fixable than it looks.Breakdown of a cold
import openai(450 ms of import time, 1099 modules):openai.types.*(non-beta)openai.types.beta.*pydantic*openaicoreopenai.lib.*The
openai.types.beta.*row is the interesting one: 30% of everyimport openai, for the Assistants API, paid by everyone who never touches it. It is not pulled in byopenai/types/__init__.py— that file has nobetareference. The chain is:_assistants.pyalready hasfrom __future__ import annotations, so all but two of those names are only needed by type checkers. The exceptions areRunStep(construct_type(type_=RunStep, ...)inaccumulate_run_step) andMessageContent(twice inaccumulate_event), both inside function bodies.Moving the imports under
TYPE_CHECKINGand importing those two locally gets, measured from a clean checkout with the repo's own venv, 25 cold runs each:sys.modulesopenai.types.betamain1.40x, −102 ms, −318 modules.
openai.AssistantEventHandlerandopenai.AsyncAssistantEventHandlerstay eagerly exported, so there is no public API change and no module-level__getattr__.This also explains why #2950 landed at only ~4%: it deferred
openai.libitself, which is the 0.9% row. The cost was never inlib— it was in what onelibmodule dragged behind it.Worth noting for the generated-code concern that sank that PR: the entire change is in
src/openai/lib/streaming/_assistants.py, which CONTRIBUTING.md says the generator never modifies, and which carries noFile generated from our OpenAPI specheader. So it is outside the Castiron custom-code budget and cannot conflict with a regen.Opened as #3727.
./scripts/lintis clean (ruff, pyright strict, mypy) and./scripts/testpasses both lanes (9127 on Pydantic v2, 9113 on v1), with a regression test that fails onmain.The remaining non-beta
openai.types.*cost (~144 ms, 434 modules) is imported fromopenai/__init__.pydirectly, so shifting that one does need a change to generated code.(Profiling done with importcost, which I wrote —
importcost profile "import openai"reproduces the first table.)perf(lib): stop pulling openai.types.beta into every import openai
marcuswood-oai commentedon Sep 18, 2026
Thanks for reporting this and sharing the profiling details! We shipped an upstream fix in #3898, available in v3.16.1, that avoids loading unused resources and Assistants types during startup. Closing this for now—please try the latest release and let me know if imports are still causing problems in your setup.