迭代xlsx文件并删除unicode python openpyxl

时间:2015-04-19 22:57:17

标签: python python-2.7 csv iteration openpyxl

我尝试将计算机上的所有Excel文件转换为CSV文件(逐页)。一些.xlsx文件非常庞大(超过100MB)。我还有几个问题:
1.我删除非unicode字符的功能非常慢
2.我不确定我是否正确使用了openpyxl的迭代,因为我还在使用大量内存而且我担心如果我真的让这个东西运行,它会出现内存错误
另外,一般来说,寻找任何编码帮助,因为我对代码一般都是新手。

import csv
from formic import FileSet
from openpyxl import load_workbook
import re
from os.path import basename
import os
import string


def uclean(s): # Clean out non-unicode chars for csv.writer - SLOW
    try:
        return ''.join(char for char in s if char in string.printable).strip()
    except:
        return ''

def fclean(s): # Clean out non-filename-safe chars
    return ''.join([c for c in s if re.match(r'\w', c)])

xlsx_files = FileSet(directory='C:\\', include='**\\*.xlsx') # the whole computer's excel files
for filename in xlsx_files:
    wb = load_workbook(filename, use_iterators=True, read_only=True)  # This is still using > 600 MBs
    for sheet in wb.worksheets:
        i = wb.worksheets.index(sheet)
        bf = os.path.splitext(
            basename(filename))[0]
        sn = fclean(str(wb.get_sheet_names()[i]))
        f = bf + '_' + sn + '.csv'
        if not os.path.exists(f):
            with open(f, 'wb') as outf:
                out_writer = csv.writer(outf)
                for row in sheet.iter_rows():
                    out_writer.writerow([uclean(cell.value) for cell in row])

2 个答案:

答案 0 :(得分:1)

使用encode会更快:

#lines is some French text
In [80]: %timeit [s.encode('ascii', errors='ignore').strip() for s in lines]
10000 loops, best of 3: 15.3 µs per loop

In [81]: %timeit [uclean(s) for s in lines]                          
1000 loops, best of 3: 522 µs per loop

至于你的openpyxl问题,我将不得不回复你 - 我现在唯一能想到的是,一次只能加载一个工作表而不是整个工作簿。请注意,由于wb是循环的局部,因此每次迭代都会被新对象替换,因此它不会像您一样使用< em>每个文件的附加 600mb内存。

答案 1 :(得分:1)

只读模式确实一次读取一个单元格,因此内存使用量最小。但是,基于您想要将所有文本转换为ascii,我想知道原因是Excel文件中有很多文本。 Excel采用优化,它将所有字符串存储在单元格引用的大列表中。如果你有很多独特的字符串,那么它们可能是任何内存问题的根源,因为我们必须将它们保存在内存中才能读取它们。

关于转换:您可以使用包装器保存为UTF-8,因此删除任何内联编码。