'Zipfile closed within context manager [duplicate]

The following code is confusing the mess out of me. I've got a zip file which I am opening in a context manager. I'm trying to extract the contents of this zip file to a temporary directory. However, when I execute this code block, it tells me that there was an "Attempt to read ZIP archive that was already closed". I find this very strange, as the zip file in question was opened in (with?) a context manager! I've inserted several print statements for calls to methods/properties associated with the object at hand. They return successfully.

Where have I gone wrong? Why does the file believe itself closed?

Any help would be appreciated!

(Edit) Please find the traceback below.

Also, is there a better way to check if a zipfile is in fact open? Other than checking if .fp is True/False?

if config.get('settings', 'new_quarter') == "Yes":
        #This gets the latest zip file, by year and quarter
        new_statements_path = os.path.join(config.get('cleaning', 'historic_dir'), 'sql_files')
        for directory,dirnames, filenames in os.walk(new_statements_path):
            zips = [f for f in filenames if ".zip" in f]
            highest_quarter = max([z.split('Q')[1].split('.')[0] for z in zips])
            print 'Targeting this quarter for initial tables: %s' % (highest_quarter)
            for z in zips:
                if 'sql_files' in f:
                    if z.split('Q')[1].split('.')[0] == highest_quarter:
                        with zipfile.ZipFile(os.path.join(directory,z), 'r') as zip_f:
                            print zip_f.fp
                            initial_tables = tempfile.mkdtemp()
                            print 'initial tables', initial_tables, os.path.exists(initial_tables) 
                            #Ensure the file is read/write by the creator only
                            saved_umask = os.umask(0077)

                            try:
                                print zip_f.namelist()
                                print zip_f.fp
                                zip_f.printdir()

                                zip_f.extractall(path=initial_tables)
                            except:
                                print traceback.format_exc()
                                os.umask(saved_umask)
                                if os.path.exists(initial_tables) == True:
                                    shutil.rmtree(initial_tables)

Traceback:

Traceback (most recent call last):
  File "/Users/n/GitHub/s/s/s/extract/extract.py", line 60, in extract_process
    zip_f.extractall(path=initial_tables)
  File "/Users/n/anaconda/lib/python2.7/zipfile.py", line 1043, in extractall
    self.extract(zipinfo, path, pwd)
  File "/Users/n/anaconda/lib/python2.7/zipfile.py", line 1031, in extract
     return self._extract_member(member, path, pwd)
  File "/Users/n/anaconda/lib/python2.7/zipfile.py", line 1085, in _extract_member
    with self.open(member, pwd=pwd) as source, \
  File "/Users/n/anaconda/lib/python2.7/zipfile.py", line 946, in open
    "Attempt to read ZIP archive that was already closed"
RuntimeError: Attempt to read ZIP archive that was already closed

(SECOND EDIT)

Here's the (reasonably) minimal & complete version. In this case, the code runs fine. Which makes sense, there's nothing fancy going on. What's interesting is I placed the full example (the one below) immediately above the previous example (above). The code below still executes just fine, but the code above still produces the same error. The only difference however is the new_statements_path variable. In the code above, this string comes from a config file. Surely, this isn't the root of the error. But I can't see any other differences.

import traceback
import os
import zipfile
import tempfile
import shutil

new_statements_path = '/Users/n/Official/sql_files'
for directory,dirnames, filenames in os.walk(new_statements_path):
    zips = [f for f in filenames if ".zip" in f]
    highest_quarter = max([z.split('Q')[1].split('.')[0] for z in zips])
    print 'Targeting this Quarter for initial tables: %s' % (highest_quarter)
    for z in zips:
            if 'sql_files' in f:
                    if z.split('Q')[1].split('.')[0] == highest_quarter:
                            with zipfile.ZipFile(os.path.join(directory,z), 'r') as zip_f:
                                    print zip_f.fp
                                    initial_tables = tempfile.mkdtemp()
                                    print 'initial tables', initial_tables, os.path.exists(initial_tables) 
                                    #Ensure the file is read/write by the creator only
                                    saved_umask = os.umask(0077)

                                    try:
                                            print zip_f.namelist()
                                            print zip_f.fp
                                            zip_f.printdir()
                                            zip_f.extractall(path=initial_tables)
                                    except:
                                            print traceback.format_exc()
                                            os.umask(saved_umask)
                                            if os.path.exists(initial_tables) == True:
                                                    shutil.rmtree(initial_tables)

    if os.path.exists(initial_tables) == True:
            shutil.rmtree(initial_tables)


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source