2009-12-27 43 views
0

我正在創建一個Python腳本,它接受遠程文件和n個線程的路徑。當每個線程完成時,文件的大小將除以線程數,我希望它們將獲取數據追加到本地文件。使用Python與線程文件下載

如何管理它,以便在那裏產生的線程將附加到本地文件,以使這些字節不得到擾亂秩序?

而且,如果我有什麼可以同時下載多個文件?

+1

你應該接受一些你的問題的答案,否則人們可能不會幫你。 – 2009-12-27 05:09:49

+0

是啊,對不起。 :D – Marconi 2009-12-27 14:48:33

回答

9

您可以使用鎖來協調作品& c,但我建議改爲使用Queue - 通常是協調Python中的多線程(和多處理)的最佳方式。

我會在主線程產卵的工作線程,你認爲合適的(你可能要性能之間進行校準,並在遠程服務器上的負載,通過實驗);同時全球Queue.Queue實例的每個工作線程等待,把它workQ例如,對於「工作要求」(wr = workQ.get()會做正確 - 每個工作請求是由一個工作線程,沒有什麼大驚小怪的,沒有搞亂獲得)。

A「工作請求」在此可以簡單地是一個三元組(元組具有三個項目):從該被請求從它那裏得到的數據的遠程文件(URL或其他),偏移的識別,字節數從中獲得(請注意,這對於一個或多個文件獲取也同樣適用)。

主線程推動各項工作要求的workQ(只是workQ.put((url, from, numbytes))每個請求),並等待結果來到另一個Queue實例,調用它resultQ(每個結果也將是一個三:文件的標識,首發偏移量,是該文件在該偏移量處的結果字節串)。

由於每個工作線程滿足它做的請求時,它會將結果納入resultQ並返回去取另一工作請求(或等待一個)。與此同時,主線程(或者如果需要,單獨的專用「寫線程」 - 即,如果主線程有其他工作要做,例如在GUI上)從resultQ得到結果並且執行所需的open,seekwrite操作將數據放在正確的位置。

有幾種方法來終止操作:例如,一個特殊的工作要求可能會問線程接收它終止 - 在主線程穿workQ正如許多那些因爲有工作線程,畢竟實際的工作請求,然後在接收和寫入所有數據時加入所有的工作線程(存在許多替代方案,例如直接加入隊列,使工作線程守護進程,以便在主線程終止時它們就會消失,等等)。

+0

真的很好,謝謝! – Marconi 2009-12-27 06:19:38

1

您需要在每個線程上獲取完全獨立的文件部分。根據線程數計算塊的開始和結束位置。每個塊必須沒有明顯的重疊。

例如,如果目標文件是3000個字節長,你要使用三個線程獲取:

  • 主題1:取字節1到1000
  • 線程2:取字節2001至00年
  • 主題3:取2001字節到3000

你會預分配原始大小的空文件,並寫回文件中的相應位置。

0

你可以使用一個線程安全的「信號」,像這樣:

class Counter: 
    counter = 0 
    @classmethod 
    def inc(cls): 
    n = cls.counter = cls.counter + 1 # atomic increment and assignment 
    return n 

使用Counter.inc()返回線程之間,你可以用它來保持字節的當前塊的曲目數量增多。

話雖這麼說,沒有必要下載文件分割成多個線程,因爲下游比寫入到磁盤的方法要慢,所以下一個被下載前一個線程將永遠結束。

最好的和最耗資源的方法很簡單,就是有直接鏈接到磁盤上的文件對象下載文件描述符。

+0

線程的原因是複用下載。多個併發TCP會話將提供比單個會話高得多的吞吐量,即使在低帶寬的DSL帳戶上(特別是在這種情況下!)。您必須同步,因爲您不控制併發讀取的完成順序。 – 2009-12-27 06:05:57

+0

...'aight。 ;-) – 2009-12-27 06:26:25