我正在创建一个Python脚本,它接受远程文件和n个线程的路径。当每个线程完成时,文件的大小将除以线程数,我希望它们将获取数据追加到本地文件。使用Python与线程文件下载
如何管理它,以便在那里产生的线程将附加到本地文件,以使这些字节不得到扰乱秩序?
而且,如果我有什么可以同时下载多个文件?
我正在创建一个Python脚本,它接受远程文件和n个线程的路径。当每个线程完成时,文件的大小将除以线程数,我希望它们将获取数据追加到本地文件。使用Python与线程文件下载
如何管理它,以便在那里产生的线程将附加到本地文件,以使这些字节不得到扰乱秩序?
而且,如果我有什么可以同时下载多个文件?
您可以使用锁来协调作品& c,但我建议改为使用Queue - 通常是协调Python中的多线程(和多处理)的最佳方式。
我会在主线程产卵的工作线程,你认为合适的(你可能要性能之间进行校准,并在远程服务器上的负载,通过实验);同时全球Queue.Queue
实例的每个工作线程等待,把它workQ
例如,对于“工作要求”(wr = workQ.get()
会做正确 - 每个工作请求是由一个工作线程,没有什么大惊小怪的,没有搞乱获得)。
A“工作请求”在此可以简单地是一个三元组(元组具有三个项目):从该被请求从它那里得到的数据的远程文件(URL或其他),偏移的识别,字节数从中获得(请注意,这对于一个或多个文件获取也同样适用)。
主线程推动各项工作要求的workQ
(只是workQ.put((url, from, numbytes))
每个请求),并等待结果来到另一个Queue
实例,调用它resultQ
(每个结果也将是一个三:文件的标识,首发偏移量,是该文件在该偏移量处的结果字节串)。
由于每个工作线程满足它做的请求时,它会将结果纳入resultQ
并返回去取另一工作请求(或等待一个)。与此同时,主线程(或者如果需要,单独的专用“写线程” - 即,如果主线程有其他工作要做,例如在GUI上)从resultQ
得到结果并且执行所需的open
,seek
和write
操作将数据放在正确的位置。
有几种方法来终止操作:例如,一个特殊的工作要求可能会问线程接收它终止 - 在主线程穿workQ
正如许多那些因为有工作线程,毕竟实际的工作请求,然后在接收和写入所有数据时加入所有的工作线程(存在许多替代方案,例如直接加入队列,使工作线程守护进程,以便在主线程终止时它们就会消失,等等)。
真的很好,谢谢! – Marconi 2009-12-27 06:19:38
您需要在每个线程上获取完全独立的文件部分。根据线程数计算块的开始和结束位置。每个块必须没有明显的重叠。
例如,如果目标文件是3000个字节长,你要使用三个线程获取:
你会预分配原始大小的空文件,并写回文件中的相应位置。
你可以使用一个线程安全的“信号”,像这样:
class Counter:
counter = 0
@classmethod
def inc(cls):
n = cls.counter = cls.counter + 1 # atomic increment and assignment
return n
使用Counter.inc()返回线程之间,你可以用它来保持字节的当前块的曲目数量增多。
话虽这么说,没有必要下载文件分割成多个线程,因为下游比写入到磁盘的方法要慢,所以下一个被下载前一个线程将永远结束。
最好的和最耗资源的方法很简单,就是有直接链接到磁盘上的文件对象下载文件描述符。
线程的原因是复用下载。多个并发TCP会话将提供比单个会话高得多的吞吐量,即使在低带宽的DSL帐户上(特别是在这种情况下!)。您必须同步,因为您不控制并发读取的完成顺序。 – 2009-12-27 06:05:57
...'aight。 ;-) – 2009-12-27 06:26:25
对于“同时下载多个文件”,我推荐了这篇文章:Practical threaded programming with Python。它提供了一个同时下载相关的例子,通过将队列与线程相结合,我认为这值得一读。
你应该接受一些你的问题的答案,否则人们可能不会帮你。 – 2009-12-27 05:09:49
是啊,对不起。 :D – Marconi 2009-12-27 14:48:33