Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions Lib/shutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,28 @@
except ImportError:
_ZLIB_SUPPORTED = False

# bz2, lzma and compression.zstd are pure Python wrappers whose only
# importable dependency that may be missing is the extension module they
# wrap. Probe those extensions directly instead: it gives the same answer
# without executing the wrappers, which shutil only needs when an archive
# is actually created or extracted.
try:
import bz2
del bz2
import _bz2
del _bz2
_BZ2_SUPPORTED = True
except ImportError:
_BZ2_SUPPORTED = False

try:
import lzma
del lzma
import _lzma
del _lzma
_LZMA_SUPPORTED = True
except ImportError:
_LZMA_SUPPORTED = False

try:
from compression import zstd
del zstd
import _zstd
del _zstd
_ZSTD_SUPPORTED = True
except ImportError:
_ZSTD_SUPPORTED = False
Expand Down
9 changes: 9 additions & 0 deletions Lib/test/test_shutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
from test import support
from test.support import os_helper, socket_helper
from test.support.os_helper import TESTFN, FakePath
from test.support.import_helper import ensure_lazy_imports

TESTFN2 = TESTFN + "2"
TESTFN_SRC = TESTFN + "_SRC"
Expand Down Expand Up @@ -2321,6 +2322,14 @@ def _boo(filename, extract_dir, extra):
unregister_unpack_format('Boo2')
self.assertEqual(get_unpack_formats(), formats)

def test_compression_wrappers_not_imported_by_shutil(self):
# gh-154904: Importing shutil must not pull in the compression
# wrappers: they are only needed once an archive is actually created
# or extracted, and importing them measurably slows down every
# process that uses shutil.
ensure_lazy_imports("shutil",
{"bz2", "lzma", "compression", "compression.zstd"})


class TestMisc(BaseTest, unittest.TestCase):

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Speed up :mod:`shutil` import by probing the ``_bz2``, ``_lzma`` and
``_zstd`` extension modules instead of importing the :mod:`bz2`,
:mod:`lzma` and :mod:`compression.zstd` wrappers, which are now only
imported when an archive is actually created or extracted.
Loading