2009-12-27 104 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