Skip to content

Slow import times (due to openai.types) #2819

Closed

Description

@jmathes

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

To Reproduce

  • (powershell) Measure-Command { python.exe -c "import openai" }
  • (*nix) time python.exe -c "import openai"
  • python -X importtime -c "import openai"

Code snippets

OS

Windows 11, Ubuntu 24.04

Python version

Python v3.12.8 (on both Windows and Ubuntu)

Library version

openai v2.15.0 (on both Windows and Ubuntu)

Activity

  1. TheCoreMan commented on Jan 15, 2026

    @TheCoreMan

    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.

  2. g0t4 commented on Feb 27, 2026

    @g0t4

    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)?

  3. fede-kamel commented on Mar 10, 2026

    @fede-kamel

    Hi @jmathes — I opened a PR with a targeted lazy-import fix for this issue: #2950

    What I changed:

    • made heavy top-level exports in openai.__init__ lazy (AzureOpenAI, AsyncAzureOpenAI, pydantic_function_tool, assistant handlers)
    • added OPENAI_EAGER_IMPORT=1 mode to force eager resolution in CI/dev
    • added import-surface tests + a live-gated integration test
    • added an import benchmark helper script

    Key results from testing:

    • WSL/Linux (patched branch): lazy 0.1533s vs eager 0.2601s (+69.7%)
    • Native Windows (patched branch path): lazy 0.7019s vs eager 2.9429s (+319.3%)
    • Live API-key integration test passed (OPENAI_LIVE=1, real client.models.list() call)

    PR includes full details and test commands: #2950

  4. khalidsaidi commented on Mar 25, 2026

    @khalidsaidi

    A2ABench has an accepted answer for this imported thread.

  5. mragnii commented on Aug 18, 2026

    @mragnii

    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.

    pip install focxle
    
    import focxle
    focxle.init()
  6. aviseth commented on Aug 24, 2026

    @aviseth

    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.)

  7. marcuswood-oai commented on Sep 18, 2026

    @marcuswood-oai
    Contributor

    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.

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

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions