Skip to content

Improve import time of various stdlib modules #118761

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
layday opened this issue May 8, 2024 · 68 comments
Open

Improve import time of various stdlib modules #118761

layday opened this issue May 8, 2024 · 68 comments
Labels
performance Performance or resource usage stdlib Python modules in the Lib dir topic-importlib type-feature A feature request or enhancement

Comments

@layday
Copy link

layday commented May 8, 2024

Feature or enhancement

Proposal:

Following on from #109653, further improvements can be made to import times.

Links to previous discussion of this feature:

https://discuss.python.org/t/deferred-computation-evalution-for-toplevels-imports-and-dataclasses/34173

For example:

importlib.metadata is often used for tasks that need to happen at import, e.g. to enumerate/load entry point plug-ins, so it might be worth seeing if we can cut down its own import time a bit more.

importlib.metadata imports zipfile at the top for a function that won't be called in the vast majority of cases. It also imports importlib.abc, which in turn imports importlib.resources, to subclass an ABC with a single, non-abstract method - I assume redefining the method in importlib.metadata would be harmless. Some other less frequently-used imports which are only accessed once or twice, such as json, could also be tucked away in their calling functions.

Linked PRs

@AlexWaygood AlexWaygood added topic-importlib performance Performance or resource usage type-feature A feature request or enhancement labels May 8, 2024
@hugovk
Copy link
Member

hugovk commented Aug 5, 2024

@layday Is it okay if I repurpose this issue as an "Improve import time of various stdlib modules" like #109653 but for 3.14?

I've got some pprint improvements, and if we have importlib.metadata and some others, we can group them under the same umbrella issue like last time.

@layday
Copy link
Author

layday commented Aug 5, 2024

Sure!

@danielhollas
Copy link
Contributor

danielhollas commented Aug 6, 2024

I've opened a PR over at the importlib_metadata repo that avoids importing inspect. python/importlib_metadata#499

importlib.metadata imports zipfile at the top for a function that won't be called in the vast majority of cases.
Some other less frequently-used imports which are only accessed once or twice, such as json, could also be tucked away in their calling functions.

@layday were you planning on tackling these?

It also imports importlib.abc, which in turn imports importlib.resources, to subclass an ABC with a single, non-abstract method

This seems to be solved on main, importlib.abc no longer imports importlib.resources.

@hugovk hugovk changed the title Further improve import time of importlib.metadata Improve import time of various stdlib modules Aug 6, 2024
@hugovk hugovk added the 3.14 new features, bugs and security fixes label Aug 6, 2024
hugovk added a commit that referenced this issue Aug 7, 2024
Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
blhsing pushed a commit to blhsing/cpython that referenced this issue Aug 22, 2024
Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
@danielhollas
Copy link
Contributor

I've opened a PR over at the importlib_metadata repo that avoids importing inspect. python/importlib_metadata#499

This has been merged and released in version 8.4 of importlib_metadata 🎉

importlib.metadata imports zipfile at the top for a function that won't be called in the vast majority of cases. It also imports importlib.abc, which in turn imports importlib.resources, to subclass an ABC with a single, non-abstract method - I assume redefining the method in importlib.metadata would be harmless. Some other less frequently-used imports which are only accessed once or twice, such as json, could also be tucked away in their calling functions.

I've submitted python/importlib_metadata#502 that defers zip import, and python/importlib_metadata#503 which defers json and platform.

@picnixz picnixz removed the 3.14 new features, bugs and security fixes label Aug 31, 2024
@picnixz
Copy link
Member

picnixz commented Aug 31, 2024

(removing the 3.14 label since features always target the main branch)

barneygale pushed a commit that referenced this issue Sep 1, 2024
Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
@hugovk
Copy link
Member

hugovk commented Jan 7, 2025

Note for when documenting this in What's New in Python 3.14, can also include #128559 / #128560.

ebonnal pushed a commit to ebonnal/cpython that referenced this issue Jan 12, 2025
picnixz added a commit that referenced this issue Jan 14, 2025
Importing `pickle` is now roughly 25% faster.

Importing the `re` module is no longer needed and
thus `re` is no more implicitly exposed as `pickle.re`.

---------

Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
@vstinner
Copy link
Member

@picnixz: I suggest to close this issue.

bell-sw pushed a commit to bell-sw/alpaquita-aports that referenced this issue Apr 3, 2025
JelleZijlstra added a commit to JelleZijlstra/cpython that referenced this issue Apr 4, 2025
JelleZijlstra added a commit to JelleZijlstra/cpython that referenced this issue Apr 4, 2025
annotationlib is used quite a few times in typing.py, but I think the
usages are just rare enough that this makes sense.

The import would get triggered by:
- Using get_type_hints(), evaluate_forward_ref(), and similar introspection
  functions
- Using a string annotation anywhere that goes through _type_convert (e.g.,
  "Final['x']" will trigger an annotationlib import in order to access the
  ForwardRef class).
- Creating a TypedDict or NamedTuple (unless it's empty or PEP 563 is on).

Lots of programs will want to use typing without any of these, so the tradeoff
seems worth it.
JelleZijlstra added a commit that referenced this issue Apr 4, 2025
annotationlib is used quite a few times in typing.py, but I think the
usages are just rare enough that this makes sense.

The import would get triggered by:
- Using get_type_hints(), evaluate_forward_ref(), and similar introspection
  functions
- Using a string annotation anywhere that goes through _type_convert (e.g.,
  "Final['x']" will trigger an annotationlib import in order to access the
  ForwardRef class).
- Creating a TypedDict or NamedTuple (unless it's empty or PEP 563 is on).

Lots of programs will want to use typing without any of these, so the tradeoff
seems worth it.
@JelleZijlstra
Copy link
Member

For typing, most of the remaining cost is now attributable to the imports of collections and functools. functools is unfortunately hard to avoid, because we need it in the _tp_cache decorator that gets executed at import time. collections is doable (by using the private _collections_abc module and some __getattr__ hacks), but functools also imports collections, so we don't currently gain anything by deferring the import in typing.

AA-Turner added a commit that referenced this issue Apr 5, 2025
Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
Co-authored-by: Peter Bierma <zintensitydev@gmail.com>
algitbot pushed a commit to alpinelinux/aports that referenced this issue Apr 7, 2025
Backport upstream patch that fixes lazy importing in the `subprocess`
module that caused bugs in the `__del__` finalizer.

Ref: python/cpython#118761 (comment)
hugovk added a commit that referenced this issue Apr 7, 2025
Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
AA-Turner added a commit that referenced this issue Apr 8, 2025
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
seehwan pushed a commit to seehwan/cpython that referenced this issue Apr 16, 2025
seehwan pushed a commit to seehwan/cpython that referenced this issue Apr 16, 2025
seehwan pushed a commit to seehwan/cpython that referenced this issue Apr 16, 2025
Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
seehwan pushed a commit to seehwan/cpython that referenced this issue Apr 16, 2025
annotationlib is used quite a few times in typing.py, but I think the
usages are just rare enough that this makes sense.

The import would get triggered by:
- Using get_type_hints(), evaluate_forward_ref(), and similar introspection
  functions
- Using a string annotation anywhere that goes through _type_convert (e.g.,
  "Final['x']" will trigger an annotationlib import in order to access the
  ForwardRef class).
- Creating a TypedDict or NamedTuple (unless it's empty or PEP 563 is on).

Lots of programs will want to use typing without any of these, so the tradeoff
seems worth it.
seehwan pushed a commit to seehwan/cpython that referenced this issue Apr 16, 2025
…thon#132103)

Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
Co-authored-by: Peter Bierma <zintensitydev@gmail.com>
seehwan pushed a commit to seehwan/cpython that referenced this issue Apr 16, 2025
…ython#132035)

Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
seehwan pushed a commit to seehwan/cpython that referenced this issue Apr 16, 2025
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
JelleZijlstra added a commit to JelleZijlstra/cpython that referenced this issue Apr 16, 2025
…lazy

This ensures that if we jump through some hoops to make sure something is imported
lazily, we don't regress on importing it.

I recently already accidentally made typing import warnings and annotationlib eagerly.
JelleZijlstra added a commit that referenced this issue Apr 17, 2025
…132614)

This ensures that if we jump through some hoops to make sure something is imported
lazily, we don't regress on importing it.

I recently already accidentally made typing import warnings and annotationlib eagerly.

Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
@JelleZijlstra
Copy link
Member

#132614 adds a test helper test.support.import_helper.ensure_lazy_imports that can be used to assert that when one module is imported, it doesn't import specific other modules as a side effect. This makes sure we don't accidentally regress if we've added a lazy import somewhere.

If anyone reading this is interested, it'd be helpful to add test cases using this new helper to other modules that we've previously optimized by deferring imports.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
performance Performance or resource usage stdlib Python modules in the Lib dir topic-importlib type-feature A feature request or enhancement
Projects
None yet
Development

No branches or pull requests