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
{{ message }}
Repository navigation
Importing bz2 will succeed under lazy_imports=all even if bz2 is not supported #150167
Edit: Originally this bug was expressed through shutil's support detection. shutil now directly imports from _bz2 which works around this issue.
Bug description:
Under lazy_imports=all, modules imported in a try/except block are still imported eagerly. However, imports that occur within that module are still imported lazily.
This may be intentional, but this bug is the result of that behaviour.
The try/except check is on bz2, which succeeds because the import to _bz2 which would fail is converted to a lazy import and is not used at top level so the import which would fail isn't triggered.
shutil could directly check _bz2 in this particular case, but I expect this pattern isn't uncommon. I looked into this after I ran into a similar issue with pip and rich with an OS-specific import that should have failed in a similar manner.
Related: #149640 as this also causes test_shutil to fail under lazy_imports=all if _bz2 isn't present.
_ZLIB_SUPPORTED, _LZMA_SUPPORTED and _ZSTD_SUPPORTED are correct since import zlib, import lzma and from compression import zstd fail immediately with ModuleNotFound even with PYTHON_LAZY_IMPORTS=all.
_BZ2_SUPPORTED is incorrect because import bz2 completes successfully even if import _bz2 will fail. It behaves differently since _bz2 symbols are only accessed when bz2 functions are called, not at import time.
lzma is working somewhat by luck as it uses a * import on the _lzma module and * imports can't be made lazy. zstd uses _zstd at module level so similarly escapes this issue. I say by luck as these aren't done with the intention of preventing the lazy import, it's just a side-effect.
I believe zlib itself is the module that would fail so its check isn't affected but I haven't confirmed this.
The simplest solution for _bz2 specifically is probably to add import _bz2; _bz2 to bz2.py to force the resolution. lzma and zstd could also do the same, but I'm not sure it's necessary as long as there are tests. (I'm not actually sure how you'd write the test for this case given it requires missing modules and the lazy import flag.)
We could instead check the internal modules directly in shutil but that makes shutil dependant on internals of the compression libraries which is probably undesirable?
Perhaps compression should have some kind of function or attribute that provides a list or set of available compression types?
I think there it would be fine to only check the internal modules and shutil could then use this directly rather than checking all of the modules itself.
I was having a look at writing a test for this and noticed that the test.support.requires_<format> functions have the same logic and probably the same issue.
So I believe the specific case of failure in shutil has been resolved as a side effect of #154908 but the logical issue still exists in other places that do check the modules directly like test.support. Not sure what to do here.
changed the title [-]`shutil._BZ2_SUPPORTED` is always `True` under `lazy_imports=all` even if it is not supported[/-][+]Importing `bz2` will succeed under `lazy_imports=all` even if `bz2` is not supported[/+]on Sep 8, 2026
changed the title [-]Importing `bz2` will succeed under `lazy_imports=all` even if `bz2` is not supported[/-][+]Importing `bz2` will succeed under `lazy_imports=all` even if bz2 is not supported[/+]on Sep 8, 2026
Activity
vstinner commentedon May 21, 2026
I can reproduce the issue on Linux using:
_ZLIB_SUPPORTED,_LZMA_SUPPORTEDand_ZSTD_SUPPORTEDare correct sinceimport zlib,import lzmaandfrom compression import zstdfail immediately withModuleNotFoundeven withPYTHON_LAZY_IMPORTS=all._BZ2_SUPPORTEDis incorrect becauseimport bz2completes successfully even ifimport _bz2will fail. It behaves differently since_bz2symbols are only accessed whenbz2functions are called, not at import time.DavidCEllis commentedon May 22, 2026
lzmais working somewhat by luck as it uses a*import on the_lzmamodule and*imports can't be made lazy.zstduses_zstdat module level so similarly escapes this issue. I say by luck as these aren't done with the intention of preventing the lazy import, it's just a side-effect.I believe
zlibitself is the module that would fail so its check isn't affected but I haven't confirmed this.The simplest solution for
_bz2specifically is probably to addimport _bz2; _bz2tobz2.pyto force the resolution.lzmaandzstdcould also do the same, but I'm not sure it's necessary as long as there are tests. (I'm not actually sure how you'd write the test for this case given it requires missing modules and the lazy import flag.)We could instead check the internal modules directly in
shutilbut that makesshutildependant on internals of the compression libraries which is probably undesirable?pythongh-150167: Make shutil compression probes eager
DavidCEllis commentedon Jun 2, 2026
Perhaps
compressionshould have some kind of function or attribute that provides a list or set of available compression types?I think there it would be fine to only check the internal modules and
shutilcould then use this directly rather than checking all of the modules itself.DavidCEllis commentedon Jul 27, 2026
I was having a look at writing a test for this and noticed that the
test.support.requires_<format>functions have the same logic and probably the same issue.cpython/Lib/test/support/__init__.py
Lines 548 to 581 in 993a0c6
DavidCEllis commentedon Sep 8, 2026
So I believe the specific case of failure in shutil has been resolved as a side effect of #154908 but the logical issue still exists in other places that do check the modules directly like
test.support. Not sure what to do here.[-]`shutil._BZ2_SUPPORTED` is always `True` under `lazy_imports=all` even if it is not supported[/-][+]Importing `bz2` will succeed under `lazy_imports=all` even if `bz2` is not supported[/+][-]Importing `bz2` will succeed under `lazy_imports=all` even if `bz2` is not supported[/-][+]Importing `bz2` will succeed under `lazy_imports=all` even if bz2 is not supported[/+]