如何在使用xlutils.filter后关闭文件

1 投票
2 回答
956 浏览
提问于 2025-04-17 22:19

有没有人能帮我在使用 xlutils.filter 之后删除一个 xls 文件,并解决下面这个错误?我尝试从文件系统中删除一个 Excel 文件(我用的是 Windows 7 64 位),但是它显示:

Traceback (most recent call last):
  File "insert_n_blank_rows.py", line 93, in <module>
    main()
  File "insert_n_blank_rows.py", line 89, in main
    insert_n_blank_rows(inputfile, n_rows, position)
  File "insert_n_blank_rows.py", line 80, in insert_n_blank_rows
    os.remove(filename)
WindowsError: [Error 32] The process cannot access the file because it is being
used by another process: 'text.xls'

我想遵循一个明智的建议,就是只用以下方式打开文件:

with open(inputfile) as f:
    ...

然后在 with 语句结束后再删除文件,但我不知道在这种情况下该怎么做。有没有人能重现这个错误?如果可以的话,有没有人能给我一些解决这个问题的建议?你可以用一个 Excel 97 格式的表格作为输入文件,里面有 4 行文本,只有 1 列。

我的 Python 文件 "insert_n_blank_rows.py" 是:

__author__ = "Arjen Jellema"

"""
This script will insert n empty rows after an excelsheetposition
into a excel sheet using module xlrd and xlwt
first it copies the file
and then inserts empty rows
then saves the new file
then removes the old file
"""

import os
import sys
import xlrd
import xlwt
from xlutils.filter import BaseReader, BaseFilter, BaseWriter, process

def insert_n_blank_rows(filename, n_rows, position):
    # this function will insert n blank row right after position as read from
    # an Excelsheet; so the cell A1 has row 1

    class Reader(BaseReader):
        def get_filepaths(self):
            return [os.path.abspath(filename)]

    class Filter(BaseFilter):
        pending_row = None
        def workbook(self,rdbook,wtbook_name):
            self.next.workbook(rdbook,filename+'.new')
        def row(self,rdrowx,wtrowx):
            self.pending_row = (rdrowx,wtrowx)
        def cell(self,rdrowx,rdcolx,wtrowx,wtcolx):
            row_offset = 0
            col_offset = 0
            buildHistoryIndexEnd = position
            if rdrowx >= buildHistoryIndexEnd:
                row_offset = 1
            if rdcolx > 1:
                col_offset = 0

            self.next.cell(rdrowx,rdcolx,wtrowx+row_offset,wtcolx+col_offset)

    class Writer(BaseWriter):
        def get_stream(self,filename):
            return file(filename,'wb')

    if n_rows == 0 or n_rows < 0:
        # give warning
        print "Warning: number of rows is equal to or smaller than 0,",
        print " nothing inserted"
        raw_input()
        sys.exit()
    elif n_rows == 1:
        # inserts 1 empty row or column in sheet
        process(Reader(),Filter(),Writer())
    elif n_rows == 2:
        # inserts 2 empty rows or columns in sheet
        process(Reader(),Filter(),Filter(),Writer())
    elif n_rows == 3:
        # inserts 3 empty rows or columns in sheet
        process(Reader(),Filter(),Filter(),Filter(),Writer())
    elif n_rows == 4:
        # inserts 4 empty rows or columns in sheet
        process(Reader(),Filter(),Filter(),Filter(),Filter(),Writer())
    elif n_rows == 5:
        # inserts 5 empty rows or columns in sheet
        process(Reader(),Filter(),Filter(),Filter(),Filter(),Filter(),Writer())
    elif n_rows > 5:
        # give warning
        print "Warning: number of rows exceeds 5,",
        print " nothing inserted"
        raw_input()
        sys.exit()
    else:
        print "Warning, something unexpected happened"
        raw_input()
        sys.exit()

    # remove old file
    os.remove(filename)
    os.rename(filename+".new", filename.rstrip('.new'))

def main():
    inputfile = "text.xls"

    # this will insert n rows after position
    n_rows = 3
    position = 1
    insert_n_blank_rows(inputfile, n_rows, position)


if __name__ == "__main__":
    main()
    sys.exit()

2 个回答

0

好的,问题出在 on_demand=True 这个选项上。通过简单地重写 get_filepaths() 方法在 class Reader(BaseReader) 里,我解决了我的问题。所以这个类应该写成:

class Reader(BaseReader):
    def get_filepaths(self):
        #print "os.path.abspath(filename): %s" % os.path.abspath(filename)
        return [os.path.abspath(filename)]

    def get_workbooks(self):
        for path in self.get_filepaths():
            yield (
                xlrd.open_workbook(
                    path,
                    formatting_info=1,
                    on_demand=False,
                    ragged_rows=True),
                os.path.split(path)[1]
                )
0

也许你需要在删除文件之前先关闭它。

http://pythonhosted.org/xlutils/filter.html#directorywriter

这里提到的内容是关于如何在使用get_stream返回的文件上调用close()方法。

我对你正在使用的库不太熟悉,但希望这些信息能对你有所帮助。

撰写回答