Skip to content

gh-141276: Avoid compiling zipimport source in get_filename - #153799

Open
harjothkhara wants to merge 3 commits into
python:mainfrom
harjothkhara:codex/gh-141276-zipimport
Open

harjothkhara wants to merge 3 commits into
python:mainfrom
harjothkhara:codex/gh-141276-zipimport

Conversation

@harjothkhara

@harjothkhara harjothkhara commented Jul 16, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • avoid compiling zipimport source while resolving a module filename
  • preserve bytecode validation and source fallback behavior
  • add a regression test and a NEWS entry

Root cause

zipimporter.get_filename() called _get_module_code(), which compiled source while import machinery was creating the module spec. Module execution then compiled the same source again.

Tests

  • ./python.exe -m test test_zipimport -m test_syntax_warning -m testBadMagic -m testBadMTime
  • ./python.exe -m test test_zipimport

Refs #141276

Duplicate-work check

No open or merged pull request referencing #141276 was found before submission.

AI assistance

OpenAI Codex assisted with investigation, implementation, testing, and review.

@brettcannon
brettcannon removed their request for review July 17, 2026 19:12
@harjothkhara

harjothkhara commented Sep 3, 2026 •

Copy link
Copy Markdown
Contributor Author

This fixes the duplicated SyntaxWarning from #141276, could someone take a look?

@itamaro itamaro left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the fix generally looks good to me, thanks for the PR!

see inline comments regarding skipping wasted source load.

a few additional requests:

  1. this is an observable behavior change, which needs to be called out in the NEWS.

the semantic change - previously, py files with syntax errors in zip would raise from find_spec() and get_filename(). after this change, find_spec() and get_filename() would succeed, and only exec_module() would raise.

while this sounds like a significant behavior change, I think it's acceptable and even desirable, because it brings zipimport in line with the standard filesystem based finder/loader - but it does warrant more explicit coverage in NEWS.
this also makes it somewhat risky to backport, so I'd like @serhiy-storchaka's opinion here as well.

  1. I'd like to see a few more test cases covering the expected behavior, and preventing unintended future regressions, especially around the subtler corners.

a test that with a py with SyntaxError. assert that find_spec() and get_filename() succeed and return expected spec / filename, and exec_module() raises SyntaxError.

perhaps also have a test that calls get_filename() directly and asserts no warnings.

I see testBadMagic/testBadMTime already cover stale/bad-magic .pyc falling back to .py. could you add:

  • valid .pyc + .py with a syntax error → spec picks the .pyc and import succeeds
  • package __init__.py with a syntax error + a valid sibling module of the same name → origin is __init__.py and exec raises SyntaxError (no fallthrough to the module)

Comment thread Lib/zipimport.py
Comment thread Lib/zipimport.py Outdated
Comment on lines +819 to +820
if not compile_source:
return None, ispackage, modpath

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not needed with the suggestion above

Suggested change
if not compile_source:
return None, ispackage, modpath

Comment on lines +1 to +2
Fix duplicate :exc:`SyntaxWarning` messages when importing source modules
from ZIP archives.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some prose you could use here:

zipimporter.get_filename() and find_spec() no longer compile source modules; a SyntaxError in a zipped source module is now raised when the module is executed, matching the behavior of filesystem-based loaders.

@bedevere-app

bedevere-app Bot commented Oct 3, 2026

Copy link
Copy Markdown

A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated.

Once you have made the requested changes, please leave a comment on this pull request containing the phrase I have made the requested changes; please review again. I will then notify any core developers who have left a review that you're ready for them to take another look at this pull request.

Move the compile_source=False early return above the archive read, so
get_filename() no longer decompresses source it immediately discards.
Also update the NEWS entry with itamaro's suggested wording and add
tests covering the deferred-SyntaxError behavior: find_spec()/
get_filename() succeed and get_filename() emits no warnings for a
module with a syntax error, a valid .pyc still wins over a bad
sibling .py, and a package's __init__.py error doesn't fall through
to a same-named sibling module.

@itamaro itamaro left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for making the requested changes!

please don't forget to follow the bot instructions about commenting on the PR once you've made the requested changes (it's needed so the bot updates PR labels and makes it show up in review queues again, otherwise it's more likely to go unnoticed).

we also need to update the docs (Doc/library/zipimport.rst) to match the modified get_filename behavior (raises when "module couldn't be found", not when "module couldn't be imported".

Comment on lines +1 to +3
``zipimporter.get_filename()`` and ``find_spec()`` no longer compile source
modules; a :exc:`SyntaxError` in a zipped source module is now raised when the
module is executed, matching the behavior of filesystem-based loaders.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new NEWS entry is now missing the original bugfix description

Suggested change
``zipimporter.get_filename()`` and ``find_spec()`` no longer compile source
modules; a :exc:`SyntaxError` in a zipped source module is now raised when the
module is executed, matching the behavior of filesystem-based loaders.
Fix duplicate :exc:`SyntaxWarning` messages when importing source modules
from ZIP archives. :meth:`zipimport.zipimporter.get_filename`, and therefore
:meth:`~zipimport.zipimporter.find_spec`, no longer compile source modules.
A :exc:`SyntaxError` in a zipped source module is now raised when the module
is executed rather than when it is found, matching the behavior of
filesystem-based loaders.

Comment thread Lib/zipimport.py
# bad magic number or non-matching mtime
# in byte code, try next
continue
modpath = toc_entry[0]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit (pre-existing), but worth doing since you're here -- the second modpath = toc_entry[0] is redundant and can be removed

Comment thread Lib/zipimport.py
# 'fullname'.
def _get_module_code(self, fullname):
# Get the code object associated with the module specified by 'fullname'.
# If compile_source is false, return None for source code without compiling it.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit

Suggested change
# If compile_source is false, return None for source code without compiling it.
# If compile_source is false, return None for source code without reading or compiling it.

Comment thread Lib/zipimport.py
Comment on lines 161 to 162
Return the filename for the specified module or raise ZipImportError
if it couldn't be imported.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the documented contract is now inaccurate

Suggested change
Return the filename for the specified module or raise ZipImportError
if it couldn't be found.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GitHub looks buggy, at least in how it's rendering this suggested change for me.

the only change I made was s/imported/found/ on the second line

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants