我在远程服务器上有一些拆分文件。
我已经尝试逐个下载它们并加入它们。但这需要很多时间。我用谷歌搜索,发现同时下载可能会加快速度。该脚本在Python上。
我的伪是这样的:
url1 = something
url2 = something
url3 = something
data1 = download(url1)
data2 = download(url2)
data3 = download(url3)
wait for all download to complete
join all data and save
有人能指出我可以同时加载文件的方向,并等到它们完成。
我尝试过创建一个类。但我再也无法弄清楚如何等到一切都完成。
我对线程和队列功能更感兴趣,我可以在我的平台中导入它们。
我尝试使用Thread和Queue,并在此站点上找到示例。这是代码pastebin.com/KkiMLTqR。但它不会等待或永远等待......不确定
答案 0 :(得分:5)
有两种方法可以同时做事。或者,实际上,2-3 / 4左右:
gevent
等混合greenlet /事件循环系统。如果您有1000个网址,则可能不希望同时执行1000个请求。例如,Web浏览器通常一次只执行8个请求。游泳池是一次只做8件事的好方法,所以让我们这样做。
而且,既然你一次只做了8件事,那些东西主要受I / O约束,那么线程是完美的。
我将使用futures
实现它。 (如果您使用的是Python 2.x或3.0-3.1,则需要安装backport futures
。)
import concurrent.futures
urls = ['http://example.com/foo',
'http://example.com/bar']
with concurrent.futures.ThreadPoolExecutor(max_workers=8) as executor:
result = b''.join(executor.map(download, urls))
with open('output_file', 'wb') as f:
f.write(result)
当然,您需要编写download
函数,但如果您一次执行这些函数,则与您编写的函数完全相同。
例如,使用urlopen
(如果您使用的是Python 2.x,请使用urllib2
代替urllib.request
):
def download(url):
with urllib.request.urlopen(url) as f:
return f.read()
如果你想自己学习如何构建一个线程池执行器,the source实际上非常简单,multiprocessing.pool
是stdlib中另一个很好的例子。
但是,这些都有很多过多的代码(处理弱引用以提高内存使用率,干净地关闭,提供不同的等待结果的方式,正确地传播异常等),这可能会妨碍你。
如果您查看PyPI和ActiveState,您会发现更简单的设计,例如threadpool
,您可能会发现它们更容易理解。
但这是最简单的可连接线程池:
class ThreadPool(object):
def __init__(self, max_workers):
self.queue = queue.Queue()
self.workers = [threading.Thread(target=self._worker) for _ in range(max_workers)]
def start(self):
for worker in self.workers:
worker.start()
def stop(self):
for _ in range(self.workers):
self.queue.put(None)
for worker in self.workers:
worker.join()
def submit(self, job):
self.queue.put(job)
def _worker(self):
while True:
job = self.queue.get()
if job is None:
break
job()
当然,死亡简单实现的缺点是它不像concurrent.futures.ThreadPoolExecutor
那样友好:
urls = ['http://example.com/foo',
'http://example.com/bar']
results = [list() for _ in urls]
results_lock = threading.Lock()
def download(url, i):
with urllib.request.urlopen(url) as f:
result = f.read()
with results_lock:
results[i] = url
pool = ThreadPool(max_workers=8)
pool.start()
for i, url in enumerate(urls):
pool.submit(functools.partial(download, url, i))
pool.stop()
result = b''.join(results)
with open('output_file', 'wb') as f:
f.write(result)
答案 1 :(得分:0)
您可以使用twisted之类的异步框架。
或者这是Python的线程可以做的一件事。因为你主要是IO绑定