Openpyxl的iter_行非常慢,即使read_only=True?

2024-04-29 05:30:34 发布

您现在位置:Python中文网/ 问答频道 /正文

我尝试编写一个Python-3函数,将xlsx文件中的数字数据读取到numpy数组中。我通常只想从特定的工作表中读取特定的区域。这些区域可能很小(十几个单元格),也可能很大(很容易达到5000 x 10000)。我对文本几乎不感兴趣,对函数、图形和格式一点也不感兴趣。到目前为止,我的方法如下(我编写的代码仅由我自己使用,因此我不遵循一些/许多约定和政治公众人物):

def xlsreadOnly(file, rangeName, sheet = 'Sheet1', dataOnly = True, forceNum = False):
    from openpyxl import load_workbook
    from openpyxl.utils.cell import coordinate_from_string, column_index_from_string
    from numpy import empty, nan
    import io

    with open(file, 'rb') as f:
        in_mem_file = io.BytesIO(f.read())

    wb = load_workbook(filename = in_mem_file, read_only = True, data_only = dataOnly)
    ws = wb[sheet]

    # find the indeces of left-upper and right-lower cells
    areal = rangeName
    w = areal.find(":")
    lu = coordinate_from_string(areal[0:w])
    luR = lu[1]
    luC = column_index_from_string(lu[0])
    rl = coordinate_from_string(areal[w+1:])
    rlR = rl[1]
    rlC = column_index_from_string(rl[0])
    # initialize variable raw 
    raw = empty([rlR-luR+1, rlC-luC+1], dtype = 'object')
            
    ctor = 0
    # iterate over the rows from left-upper to right-lower cell
    for row in ws.iter_rows(min_row=luR, max_row=rlR, min_col=luC, max_col=rlC, values_only=True):
        raw[ctor, :] = np.array(row)
        ctor += 1
    
    return raw

我使用了in_mem_file,因为它在早期版本中稍微加快了函数的速度。工作簿以read_only的形式加载,感兴趣的区域以左上行(luR)、右下行(lrR)的形式逐段可用。变量raw预先以适当的大小初始化,因此不存在append

有趣的部分似乎是循环

    for row in ws.iter_rows(min_row=luR, max_row=rlR, min_col=luC, max_col=rlC, values_only=True):

我读到的工作表大小为2535 x 4763。如果我读取一个大小为100 x 4763的区域,该功能需要大约4.2秒(i5-9600,3.7GHz,16GB RAM,SSD),这听起来对我来说太长了。如果我将面积减少到100x3,仍然需要4.0秒(是的,对于300个单元!)。看起来,列的数量实际上是无关紧要的。但是,时间几乎与行数成线性关系,因此将面积增加到500 x 4763大约需要22秒。读取整个文件需要相应的时间

raw[ctor, :] = np.array(row)中删除到numpy数组的转换几乎不会增加计算时间

我真的认为我错过了一些非常明显的东西,但在搜索了几天之后,我仍然没有看到它!绝望而真诚地感谢你把我的头指向我的错误

编辑:@Charlie Clark,你的评论是100%真实的,代码不太容易阅读,并且有一些不必要的代码。我做了一些改变,希望现在更好。我还根据需要更新了文本。我忘了提到从一个小工作表中读取相同的100x3区域只需几毫秒。因此,问题似乎出在(我对for循环的理解)中


Tags: infromimporttrue区域onlystringraw