當我第一次開始開發這個項目時,並沒有要求生成大文件,但它現在是可交付成果。長篇故事,GAE對任何大規模數據操作或內容生成都不太好。拋開文件存儲的缺失,甚至像使用帶有1500條記錄的ReportLab生成pdf一樣簡單,似乎會遇到DeadlineExceededError。這只是一個由表格組成的簡單pdf。如何使用AppEngine和Datastore生成大文件(PDF和CSV)?
我使用下面的代碼:
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(或小的大塊,然後我連接或處理)
在此先感謝您的任何建議。
可能是一個小小的低效率,但data.append([...])將比data + = [[...]]更有效率。 – 2010-10-15 09:21:01
我編輯了代碼來反映這一點。謝謝你的提示! – etc 2010-10-16 06:05:19