2015-09-16 126 views
3

我有一些代碼可以生成數以千計的發票作爲PDF,然後將它們寫入一個zip文件,然後通過HttpStreamingResponse(django)抽出它。 PDF的生成是真的是緩慢,目前單線程。順序處理多線程輸出

我可以很快生成PDF的源HTML。我想:

  • 生成所有的HTML(單線程,數據庫無法處理的併發查詢)
  • 這些轉換到PDF,在8個線程
  • 同步方式處理PDF文件的輸出所以我可以將它添加到我的zipstream文件中。

我已經涉足multiprocessing.Pool之前,但我不知道如何正確地做到這一點。這是一些非常近似的代碼。

def generate_statements(request): 
    htmls = [generate_html(customer) for customer in customers] 
    pdfs = [generate_pdf(html) for html in htmls] 

    # create zip file 

    for pdf in pdfs: 
     zip.writestring(...) 

    # output this to browser 

def generate_html(customer): 
    # do something that returns a string of HTML 

def generate_pdf(html): 
    # do something that creates a single pdf 

如果有,開始轉換HTML的HTMLS完成之前,甚至更好,但我需要處理的generate_pdf線性的輸出方式的選擇;我無法同時寫入zip。

(PS:我知道一些事情聽起來像功課,但請看看我的網絡配置文件,你認爲我是一個懶惰的學生之前......我是一個懶惰的專業程序員thankyouverymuch)

+0

我會用[線程](https://docs.python.org/dev/library/threading.html)和[隊列]去(https://docs.python.org /dev/library/queue.html)。我猜測生成PDF的實際工作是由外部程序完成的;如果是這樣,我會避免[multiprocessing](https://docs.python.org/dev/library/multiprocessing.html),因爲它會增加不必要的開銷。 –

+0

「數據庫無法處理併發查找」 - 獲得更好的數據庫可能是一個好的開始...... – twalberg

回答

1

這樣比較容易。下面的答案讓我想起了多處理池映射方法。這是一個異步映射 - 就像內置映射一樣。它會加入(即 - 直到完成所有異步事件纔會返回),並且您將獲得所有項目的有序列表。

htmls = [generate_html(customer) for customer in customers] 
print "Htmls is:" , repr(htmls) 
print "Starting map" 
pdf_pool = Pool(5) 
pdfs = pdf_pool.map(generate_pdf, htmls, 8) 

print "Done map" 
# zip stuff 
for pdf in pdfs: 
    print(pdf) 
+0

您可以擴展一下嗎?我已經看到了「排隊」,而爲此搜索了很多東西,但它似乎更多地用作源而不是匯。我將它作爲參數傳遞,但是如何通過同步代碼中的隊列運行? – Oli

0
from multiprocessing import Pool 
from time import sleep 

# html list that has to convert to pdf 
jobs = range(0,100000) 

def create_pdf(html,zipstream): 
    print 'starting job {}'.format(html) 
    pdf = convert_html_to_pdf(html) # finished converting, returns location of the pdf 
    try untill suceed: #implement something that checks lock on zipstream 
     zipstream.write(pdf) 
    sleep(2) 
    print 'ended job {}'.format(html) 
    #do whatever, followed by whatever requirement for this html. 


pool = Pool(processes=8) 
with ZipFile('pdfs.zip', 'w') as myzip: 
    print pool.map(create_pdf,(jobs,myzip)) # jobs is list of job 
    #... when done, 
    zipstream.close() 
+0

我的create_pdf需要寫一些我的同步代碼可以處理的內容(寫入zip)。這是這裏的問題。 – Oli

+0

這不是我想要「混合」它們,而是因爲我沒有真正將PDF存儲在磁盤上,我的PDF生成將它們作爲字節串返回,因此我可以直接將它們噴射到zip中。 – Oli

+0

我已經編輯了答案,看看這個邏輯是否符合你的要求 – taesu