Zipfile在上下文管理器

时间:2017-09-06 16:55:48

标签: python zipfile temporary-directory

下面的代码让我感到困惑。我有一个zip文件,我在上下文管理器中打开。我正在尝试将此zip文件的内容解压缩到临时目录。但是,当我执行此代码块时,它告诉我有一个“尝试读取已经关闭的ZIP存档”。我发现这很奇怪,因为有问题的zip文件在(带?)中打开了一个上下文管理器!我已经插入了几个print语句来调用与手头对象相关的方法/属性。他们成功回归。

我哪里出错了?为什么文件相信自己关闭了?

任何帮助将不胜感激!

(编辑)请找到下面的追溯。

另外,有没有更好的方法来检查zipfile是否实际上是开放的?除了检查.fp是真还是假?

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 (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

(第二次编辑)

这是(合理的)最小和&完整版。在这种情况下,代码运行正常。这是有道理的,没有什么花哨的。有趣的是我把完整的例子(下面的例子)放在上一个例子(上图)的正上方。下面的代码仍然执行得很好,但上面的代码仍然会产生相同的错误。但唯一的区别是 new_statements_path 变量。在上面的代码中,此字符串来自配置文件。当然,这不是错误的根源。但我看不出任何其他差异。

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)

0 个答案:

没有答案