1

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

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

任何帮助,将不胜感激!

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

另外,有没有更好的方法来检查一个 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)
4

0 回答 0