Да, есть один - пикурл.
Это не просто, поскольку curl низкоуровневый, но он делает именно то, что вам нужно - вы предоставляете ему несколько URL-адресов, и он загружается одновременно и асинхронно.
import pycurl
from StringIO import StringIO
def LoadMulti(urls):
m = pycurl.CurlMulti()
handles = {}
for url in urls:
c = pycurl.Curl()
c.setopt(pycurl.URL, url)
data = StringIO()
header = StringIO()
c.setopt(pycurl.WRITEFUNCTION, data.write)
c.setopt(pycurl.HEADERFUNCTION, header.write)
handles[url] = dict(data=data, header=header, handle=c)
m.add_handle(c)
while 1:
ret, num_handles = m.perform()
if ret != pycurl.E_CALL_MULTI_PERFORM: break
while num_handles:
ret = m.select(1.0)
if ret == -1: continue
while 1:
ret, num_handles = m.perform()
if ret != pycurl.E_CALL_MULTI_PERFORM: break
return handles
res = LoadMulti(['http://pycurl.sourceforge.net/doc/pycurl.html', 'http://pycurl.sourceforge.net/doc/curlobject.html', 'http://pycurl.sourceforge.net/doc/curlmultiobject.html'])
for url, d in res.iteritems():
print url, d['handle'].getinfo(pycurl.HTTP_CODE), len(d['data'].getvalue()), len(d['header'].getvalue())
Вы можете запускать обновления GUI в этих циклах while, чтобы интерфейс не зависал.