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