当我第一次开始开发这个项目时,没有要求生成大文件,但它现在是可交付的.
简而言之,GAE对于任何大规模数据处理或内容生成都不是很好.除了缺少文件存储之外,甚至像使用带有1500条记录的ReportLab生成pdf这样简单的事情似乎遇到了DeadlineExceededError.这只是一个由表组成的简单pdf.
我使用以下代码:
self.response.headers['Content-Type'] = 'application/pdf' self.response.headers['Content-Disposition'] = 'attachment; filename=output.pdf' doc = SimpleDocTemplate(self.response.out, pagesize=landscape(letter)) elements = [] dataset = Voter.all().order('addr_str') data = [['#', 'STREET', 'UNIT', 'PROFILE', 'PHONE', 'NAME', 'REPLY', 'YS', 'VOL', 'NOTES', 'MAIN ISSUE']] i = 0 r = 1 s = 100 while ( i < 1500 ): voters = dataset.fetch(s, offset=i) for voter in voters: data.append([voter.addr_num, voter.addr_str, voter.addr_unit_num, '', voter.phone, voter.firstname+' '+voter.middlename+' '+voter.lastname ]) r = r + 1 i = i + s t=Table(data, '', r*[0.4*inch], repeatRows=1 ) t.setStyle(TableStyle([('ALIGN',(0,0),(-1,-1),'CENTER'), ('INNERGRID', (0,0), (-1,-1), 0.15, colors.black), ('BOX', (0,0), (-1,-1), .15, colors.black), ('FONTSIZE', (0,0), (-1,-1), 8) ])) elements.append(t) doc.build(elements)
没有什么特别的花哨,但它窒息.有一个更好的方法吗?如果我可以写入某种文件系统并以位为单位生成文件,然后重新加入可能有效的文件,但我认为系统排除了这一点.
我需要为CSV文件做同样的事情,但是限制显然有点高,因为它只是原始输出.
self.response.headers['Content-Type'] = 'application/csv' self.response.headers['Content-Disposition'] = 'attachment; filename=output.csv' dataset = Voter.all().order('addr_str') writer = csv.writer(self.response.out,dialect='excel') writer.writerow(['#', 'STREET', 'UNIT', 'PROFILE', 'PHONE', 'NAME', 'REPLY', 'YS', 'VOL', 'NOTES', 'MAIN ISSUE']) i = 0 s = 100 while ( i < 2000 ): last_cursor = memcache.get('db_cursor') if last_cursor: dataset.with_cursor(last_cursor) voters = dataset.fetch(s) for voter in voters: writer.writerow([voter.addr_num, voter.addr_str, voter.addr_unit_num, '', voter.phone, voter.firstname+' '+voter.middlename+' '+voter.lastname]) memcache.set('db_cursor', dataset.cursor()) i = i + s memcache.delete('db_cursor')
任何建议将非常感谢.
编辑:
上面我根据我的研究记录了三种可能的解决方案,以及建议等
它们不一定是相互排斥的,可以是三者中的任何一个的轻微变化或组合,但是解决方案的要点在那里.让我知道你认为哪一个最有意义,并且可能表现最佳.
解决方案A:使用mapreduce(或任务),序列化每条记录,并为每个用键名称键入的记录创建一个memcache条目.然后将这些项单独处理到pdf/xls文件中.(使用get_multi和set_multi)
解决方案B:使用任务,序列化记录组,并将它们作为blob加载到数据库中.然后在处理完所有记录后触发任务,该记录将加载每个blob,反序列化它们,然后将数据加载到最终文件中.
解决方案C:使用mapreduce,检索键名并将它们存储为列表或序列化blob.然后按键加载记录,这将比当前加载方法更快.如果我这样做,哪个更好,将它们存储为列表(以及限制是什么......我假设一个100,000的列表超出了数据存储的能力)或者作为序列化的blob(或者小的)然后我连接或处理的块)
提前感谢任何建议.