下面的代码让我感到困惑。我有一个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)