GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — ValueError: I/O operation on closed file. in ZipFile destructor · Issue #81954 · python/cpython

ValueError: I/O operation on closed file. in ZipFile destructor #81954

New issue
Copy link
New issue
Copy link
Closed
Closed
ValueError: I/O operation on closed file. in ZipFile destructor#81954
Copy link
Labels
3.11only security fixesonly security fixes3.12only security fixesonly security fixes3.13only security fixesonly security fixesstdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error

Description

joernheissler
mannequin
opened on Aug 6, 2019
Issue body actions
BPO 37773
Nosy @pitrou, @vstinner, @serhiy-storchaka, @joernheissler, @tirkarthi, @akulakov

Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

Show more details

GitHub fields:

assignee = None
closed_at = None
created_at = <Date 2019-08-06.09:35:50.904>
labels = ['3.10', '3.9', 'type-crash', '3.11']
title = 'ValueError: I/O operation on closed file. in ZipFile destructor'
updated_at = <Date 2022-01-23.20:02:33.133>
user = 'https://github.com/joernheissler'

bugs.python.org fields:

activity = <Date 2022-01-23.20:02:33.133>
actor = 'iritkatriel'
assignee = 'none'
closed = False
closed_date = None
closer = None
components = []
creation = <Date 2019-08-06.09:35:50.904>
creator = 'joernheissler'
dependencies = []
files = []
hgrepos = []
issue_num = 37773
keywords = ['3.8regression']
message_count = 10.0
messages = ['349104', '349105', '389594', '389605', '389611', '389689', '389690', '389691', '396649', '396657']
nosy_count = 6.0
nosy_names = ['pitrou', 'vstinner', 'serhiy.storchaka', 'joernheissler', 'xtreak', 'andrei.avk']
pr_nums = []
priority = 'normal'
resolution = None
stage = None
status = 'open'
superseder = None
type = 'crash'
url = 'https://bugs.python.org/issue37773'
versions = ['Python 3.9', 'Python 3.10', 'Python 3.11']

Linked PRs

  • gh-81954: Warn when ZipFile is closed with unwritten data #152354
  • gh-81954: Use lazy import warnings in zipfile #155326
  • gh-81954: Eagerly import warnings module to failure of ZipFile.__del__ during finalization #159419

Activity

Next
  1. joernheissler commented on Aug 6, 2019

    @joernheissler
    joernheisslermannequin
    on Aug 6, 2019
    MannequinAuthor
    More actions

    When running this code:

    from zipfile import ZipFile
    import io
    
    def foo():
        pass
    
    data = io.BytesIO()
    zf = ZipFile(data, "w")

    I get this message:

    Exception ignored in: <function ZipFile.__del__ at 0x7f9005caa160>
    Traceback (most recent call last):
      File "/home/user/git/oss/cpython/Lib/zipfile.py", line 1800, in __del__
      File "/home/user/git/oss/cpython/Lib/zipfile.py", line 1817, in close
    ValueError: I/O operation on closed file.

    Comment out def foo: pass, and there is no error.

    It looks like the bug was introduced with commit ada319b (bpo-32388).

  2. joernheissler
    added
    3.8 (EOL)end of lifeend of life
    3.9 (EOL)end of lifeend of life
    type-crashA hard crash of the interpreter, possibly with a core dumpA hard crash of the interpreter, possibly with a core dump
    on Aug 6, 2019
  3. tirkarthi commented on Aug 6, 2019

    @tirkarthi
    tirkarthi
    on Aug 6, 2019
    Member
    More actions

    This looks like a regression in 3.8 so I have added 3.8 regression tag.

  4. joernheissler commented on Mar 27, 2021

    @joernheissler
    joernheisslermannequin
    on Mar 27, 2021
    MannequinAuthor
    More actions

    Still reproducible in cpython 3.10.0a3 (debian unstable) and 3.10.0a6 (pyenv).

  5. joernheissler
    added
    3.10 (EOL)end of lifeend of life
    on Mar 27, 2021
  6. serhiy-storchaka commented on Mar 27, 2021

    @serhiy-storchaka
    serhiy-storchaka
    on Mar 27, 2021
    Member
    More actions

    That's what happened. Function foo creates a reference loop. It has reference to the module dict, and the dict has reference to the function. The dict has also references to BytesIO and ZipFile objects. At shutdown stage the garbage collector is called. It founds the reference loop which contains the module dict, function foo and BytesIO and ZipFile objects. It tries to break the loop by calling the destructor of arbitrary object in the loop. In that case it is the BytesIO object. It does not help, but finally the destructor of the ZipFile object is called (either directly or after breaking the loop and destroying the module dict). The ZipFile destructor tries to close the BytesIO object, but it is already closed in its destructor.

    It is a dangerous situation which potentially can cause data corruption (if the underlying stream is closed before flushing buffers). Clearing the module dict before invoking garbage collecting would solve this issue. Making the garbage collector more clever and and avoid destroying objects if it does not break the loop would help too, but it is more complex problem and such change could not be backported to 3.8.

    Victor, were there any changes in the garbage collector or interpreter shutdown code in 3.8?

  7. joernheissler commented on Mar 27, 2021

    @joernheissler
    joernheisslermannequin
    on Mar 27, 2021
    MannequinAuthor
    More actions

    Thanks Serhiy for the explanation, it's making sense now.

    Guess whatever I did back then (no idea what I was working on) was basically a mistake; I should have closed my ZipFile properly, e.g. by using context managers. So maybe it's not really a cpython bug.

    I ran a git-bisect back then and came up with https://hg.python.org/lookup/ada319bb6d0ebcc68d3e0ef2b4279ea061877ac8 as cause.

  8. vstinner commented on Mar 29, 2021

    @vstinner
    vstinner
    on Mar 29, 2021
    Member
    More actions

    Victor, were there any changes in the garbage collector or interpreter shutdown code in 3.8?

    I took some notes there: https://pythondev.readthedocs.io/finalization.html

    I proposed bpo-42671 "Make the Python finalization more deterministic" but it will break some use cases, so I'm not comfortable with this idea yet :-(

  9. vstinner commented on Mar 29, 2021

    @vstinner
    vstinner
    on Mar 29, 2021
    Member
    More actions

    IMO ZipFile destructor should emit a ResourceWarning if it's not closed explicitly.

    Nothing in the Python specification gives you any warranty that destructors will be ever called... Depending on the Python implementation and depending on many things, you never know when a destructor is called.

    Just call the close() method explicitly.

  10. vstinner commented on Mar 29, 2021

    @vstinner
    vstinner
    on Mar 29, 2021
    Member
    More actions

    FYI TextIOWrapper has a similar issue: bpo-17852. There was an attempt to fix the issue in 2017, but it had to be reverted.

  11. akulakov commented on Jun 28, 2021

    @akulakov
    akulakov
    on Jun 28, 2021
    Contributor
    More actions

    In my testing on 3.9.1 and the current main branch, I found:

    • I can reproduce this issue if a function or a lambda or class with a method are defined.
    • There is no error if a class is defined with no methods. (I'm not sure why).

    The test code runs without errors if the following check is done before seeking the fp in close():

        if not self.fp.closed:

    here:
    https://github.com/python/cpython/blob/main/Lib/zipfile.py#L1823

    The fix also requires adding closed property to zipfile._Tellable

    With these two small changes, all test_zipfile tests pass.

    I'm not sure this is the proper fix, because this is a complex issue..

    I will go ahead and put up a PR if this seems like a good approach.

  12. akulakov commented on Jun 28, 2021

    @akulakov
    akulakov
    on Jun 28, 2021
    Contributor
    More actions

    I forgot to add, to fix the tests I also had to add closed=False attr to test_zipfile.Tellable.

  13. iritkatriel
    added
    3.11only security fixesonly security fixes
    on Jan 23, 2022
  14. 9 remaining items

  15. iritkatriel
    added
    3.12only security fixesonly security fixes
    3.13only security fixesonly security fixes
    on Oct 27, 2023
  16. iritkatriel
    added
    stdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directory
    on Nov 23, 2023
  17. serhiy-storchaka commented on May 18, 2026

    @serhiy-storchaka
    serhiy-storchaka
    on May 18, 2026
    Member
    More actions

    This issue is not specific for zipfile. You will get similar symptoms for buffered files with something in the buffer, and for any object with non-trivial destructor. This is how the garbage collector works. More smart garbage collector could see that the BytesIO should not be destroyed before the ZipFile which refers to it. It could also see that destroying the BytesIO and the ZipFile will not help to break the loop cause by the function. But this is a complex issue.

    Recommendation: always use ZipFile as the content manager, or ensure that close() is always called (in the finally block if necessary). Do not rely on the garbage collector, it can destroy object in wrong order.

    Reacted by Victor Stinner and Cody Maloney
  18. serhiy-storchaka
    marked ValueError on ephemeral zipfile after exception #106763 as a duplicate of this issue on May 18, 2026
  19. cmaloney commented on Jun 27, 2026

    @cmaloney
    cmaloney
    on Jun 27, 2026
    Contributor
    More actions

    I Created #152354 to raise ResourceWarning on this case in the same way that GzipFile and TextIOWrapper do which should make the source(s) more straightforward to find with tracemalloc.

  20. vstinner
    added a commit that references this issue on Aug 7, 2026

    gh-81954: Warn when ZipFile is closed with unwritten data (#152354)

    5e0c502
  21. vstinner commented on Aug 7, 2026

    @vstinner
    vstinner
    on Aug 7, 2026
    Member
    More actions

    The zipfile module now emits a ResourceWarning if a zipfile object is not closed explicitly and it's open in write mode. I close the issue.

  22. vstinner
    closed this as completedon Aug 7, 2026
  23. github-project-automation
    moved this to Done in Zipfile issues 📦on Aug 7, 2026
  24. github-project-automation
    moved this to Done in @serhiy-storchaka's project python-zipfileon Aug 7, 2026
  25. vstinner
    added a commit that references this issue on Aug 7, 2026

    gh-81954: Use lazy import warnings in zipfile (#155326)

    7922b67
  26. mbeijen
    added 2 commits that reference this issue on Aug 14, 2026

    pythongh-81954: Warn when ZipFile is closed with unwritten data (pyth…

    9d21558

    pythongh-81954: Use lazy import warnings in zipfile (python#155326)

    522f61d
  27. ambv
    added a commit that references this issue on Oct 23, 2026

    gh-81954: Eagerly import warnings module to failure of ZipFile.__del_…

    f9f33a6
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

    3.11only security fixesonly security fixes3.12only security fixesonly security fixes3.13only security fixesonly security fixesstdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error

    Projects

    • Zipfile issues 📦
      Status
      Done
      Show more project fields

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

    You are visitor 01402503 — GeezerVison does not store the pages you look up.
    Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.