这次的数据是放进Excel的。到后面才意识到如果放进数据库的话,可能就没有那么多事了。但是已经写到一半,难以回头了。

搜索Excel,可以得出几个方案来,一个是用xlrt/xlwt库,这个不管电脑上是否安装了Excel,都可以运行,但只能是xls格式的。还有一个是直接包装了com,需要电脑上安装了软件才行。我采用的是前一种。

基本的读写没有问题。但是数据量一大起来,就有问题了。

  • 内存不够。程序一跑起来,内存占用就一点一点往上涨。后面再查了一下,知道要用flush_row_data。但是还是会出错。一看内存占用,没有什么问题,一直很平稳。但最后还是会出现memory error。这真是见鬼了。又是反复地查, 反复地运行。一点结果都没有。要命的是bug只在数据量大起来才出现,而等数据量大起来往往要好几个小时,这debug的成本实在是太高了。一个偶然的机会,突然发现内存占用,虽然总体平稳,但是会规律性的出现小的高涨,而这规律性,会不会和flush_row_data,有关。一直疑惑的是data被flush到了哪里。原来xlwt的作法是很蛋疼的作法。把数据存在内存里,或者flush到一个temp,到save的时候,再一次性写入。而问题正出在这一次性写入,内存猛涨。那我要flush_row_data何用?为什么不一开始就flush进要写入的地方。
  • 行数限制。这个是xls格式本身决定的,最多行数只能是65536。而且数据一大,文件打开也不方便。

结合以上两点,最终采取了这么一个策略,如果行数是1000的倍数,进行一次flush,如果行数超过65536,新开一个sheet,如果超过3个sheet,则新建一个文件。为了方便,把xlwt包装了一下

#coding:utf-8#

import xlwt

class XLS:

    '''a class wrap the xlwt'''

    MAX_ROW=65536

    MAX_SHEET_NUM=3

    def __init__(self,name,captionList,typeList,encoding='utf8',flushBound=1000):

        self.name=name

        self.captionList=captionList[:]

        self.typeList=typeList[:]

        self.workbookIndex=1

        self.encoding=encoding

        self.wb=xlwt.Workbook(encoding=self.encoding)

        self.sheetIndex=1

        self.__addSheet()

        self.flushBound=flushBound

    def __addSheet(self):

        if self.sheetIndex != 1:

            self.wb.save(self.name+str(self.workbookIndex)+'.xls')

        if self.sheetIndex>XLS.MAX_SHEET_NUM:

            self.workbookIndex+=1

            self.wb=xlwt.Workbook(encoding=self.encoding)

            self.sheetIndex=1

        self.sheet=self.wb.add_sheet(self.name.encode(self.encoding)+str(self.sheetIndex))

        for i in range(len(self.captionList)):

            self.sheet.write(0,i,self.captionList[i])

        self.row=1

    def write(self,data): 

        if self.row>=XLS.MAX_ROW:

            self.sheetIndex += 1

            self.__addSheet()

        for i in range(len(data)):

            if self.typeList[i]=="num":

                try:

                    self.sheet.write(self.row,i,float(data[i]))

                except ValueError:

                    pass 

            else:

                self.sheet.write(self.row,i,data[i])

        if self.row % self.flushBound == 0:

            self.sheet.flush_row_data()

        self.row+=1

    def save(self):

        self.wb.save(self.name+str(self.workbookIndex)+'.xls')

 

相关文章:

  • 2021-04-18
  • 2022-01-16
  • 2022-12-23
  • 2022-12-23
  • 2021-05-26
  • 2021-09-03
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2021-09-12
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案