我希望能够用Python读取Excel文件,在读取完成后保持Python脚本运行做其他事情,同时能够在另一个进程中编辑Excel文件。我正在使用 python 2.7 和 openpyxl。
目前看起来像:
from openpyxl import load_workbook
def get_excel_data():
OESwb = load_workbook(filename = OESconfigFile, data_only=True,
read_only=True)
ws = OESwb.get_sheet_by_name('MC01')
aValue = ws['A1'].value
return aValue
val = get_excel_data()
运行该函数后,Excel 文件仍然被锁定,无法从其他进程访问(它给出错误“'文件名'当前正在使用中。请稍后再试”),即使我不想再在 Python 中读取它。
如何从脚本中关闭该文件?我尝试过 OESwb.close() 但它给出错误“'Workbook'对象没有属性'close'”。我找到了这篇文章,但它似乎没有帮助。
编辑: 看起来 OESwb.save('filename.xlsx') 有效,但前提是 read_only=False 。但是,最好能够关闭文件并仍处于只读模式。看来这是 openpyxl 的一个错误,因为它应该在 load_workbook 完成后关闭文件。
由于某些严酷的原因,stackoverflow 将允许我发布答案,但我没有足够的“代表”来发表评论或投票 - 所以我们在这里。
接受的答案
wb._archive.close()
对我不起作用。可能这是因为我使用的是只读模式。在“正常”模式下可能工作正常。
bmiller的答案是唯一对我有用的答案:
with open(xlsx_filename, "rb") as f:
in_mem_file = sys.io.BytesIO(f.read())
wb = load_workbook(in_mem_file, read_only=True)
正如他所说,使用 open() 加载比仅使用只读加载时更快。
我的工作代码基于 bmiller 的答案:
import openpyxl
import io
xlsx_filename=r'C:/location/of/file.xlsx'
with open(xlsx_filename, "rb") as f:
in_mem_file = sys.io.BytesIO(f.read())
wb = openpyxl.load_workbook(in_mem_file, read_only=True)
我已经尝试了所有这些以只读模式关闭 xlsx 文件的解决方案,但似乎都不起作用。 我最终使用了内存内文件:
with open(xlsx_filename, "rb") as f:
in_mem_file = io.BytesIO(f.read())
wb = load_workbook(in_mem_file, read_only=True)
甚至可能加载速度更快,无需担心关闭任何内容。
wb._archive.close()
也可以与 use_iterator 一起使用。
为了您的最新信息,openpyxl 2.4.4+ 提供了
Workbook.close()
方法。以下为参考。
http://openpyxl.readthedocs.io/en/stable/changes.html?highlight=close#id86
https://bitbucket.org/openpyxl/openpyxl/issues/673
我也发现这是一个问题,并且觉得工作簿没有 close 方法很奇怪。
我想出的解决方案是一个上下文管理器,它为我“关闭”文件,这样我就不会在每次阅读电子表格时在代码中进行无意义的保存。
@contextlib.contextmanager
def load_worksheet_with_close(filename, *args, **kwargs):
'''
Open an openpyxl worksheet and automatically close it when finished.
'''
wb = openpyxl.load_workbook(filename, *args, **kwargs)
yield wb
# Create path in temporary directory and write workbook there to force
# it to close
path = os.path.join(tempfile.gettempdir(), os.path.basename(filename))
wb.save(path)
os.remove(path)
使用方法:
with load_worksheet_with_close('myworkbook.xlsx') as wb:
# Do things with workbook
你可以尝试:
wb = None
释放资源,并在您再次需要时再次加载它,在相同或其他变量中。
使用
OESwb._archive.close()
这将关闭在 'read_only=True'
模式下保持打开状态的附加 ZipFile 文件句柄。
请注意,关闭后您无法从OESwb
读取更多数据。
另请注意,这是一种解决方法,并且 _archive
可能会在未来版本中删除。
要关闭,我相信您需要保存文件:
OESwb.save('filename.xlsx')
希望这有帮助。