urllib2 и многопоточность - PullRequest
       7

urllib2 и многопоточность

0 голосов
/ 26 января 2012

Я пытаюсь следовать примеру многопоточности, приведенному в: Python urllib2.urlopen () работает медленно, нужен лучший способ прочитать несколько URL , но мне кажется, что я получаю «ошибку потока», и я неуверен, что это действительно означает.

urlList=[list of urls to be fetched]*100
def read_url(url, queue):
 my_data=[]
 try:
    data = urllib2.urlopen(url,None,15).read()
    print('Fetched %s from %s' % (len(data), url))
    my_data.append(data)
    queue.put(data)
except HTTPError, e:
    data = urllib2.urlopen(url).read()
    print('Fetched %s from %s' % (len(data), url))
    my_data.append(data)
    queue.put(data)

def fetch_parallel():
    result = Queue.Queue()
    threads = [threading.Thread(target=read_url, args = (url,result)) for url in urlList]
    for t in threads:
      t.start()
    for t in threads:
      t.join()
    return result

res=[]  
res=fetch_parallel()
reslist = []
while not res.empty: reslist.append(res.get())
print (reslist)

Я получаю следующую первую ошибку:

Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 552, in __bootstrap_inner
self.run()
File "/usr/lib/python2.7/threading.py", line 505, in run
self.__target(*self.__args, **self.__kwargs)
File "demo.py", line 76, in read_url
print('Fetched %s from %s' % (len(data), url))
TypeError: object of type 'instancemethod' has no len()

С другой стороны, я вижу, что иногда кажется, что данные извлекаются, но затемЯ получаю следующую вторую ошибку:

Traceback (most recent call last):
File "demo.py", line 89, in <module>
print str(res[0])
AttributeError: Queue instance has no attribute '__getitem__'

При получении данных почему результат не отображается в res []?Спасибо за ваше время.

Обновление После изменения read на read () в функции read_url (), хотя ситуация улучшилась (теперь я получаю много выборок страниц), но все же получилошибка:

Exception in thread Thread-86:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 552, in __bootstrap_inner
self.run()
File "/usr/lib/python2.7/threading.py", line 505, in run
self.__target(*self.__args, **self.__kwargs)
File "demo.py", line 75, in read_url
data = urllib2.urlopen(url).read()
File "/usr/lib/python2.7/urllib2.py", line 126, in urlopen
return _opener.open(url, data, timeout)
File "/usr/lib/python2.7/urllib2.py", line 397, in open
response = meth(req, response)
File "/usr/lib/python2.7/urllib2.py", line 510, in http_response
'http', request, response, code, msg, hdrs)
File "/usr/lib/python2.7/urllib2.py", line 429, in error
result = self._call_chain(*args)
File "/usr/lib/python2.7/urllib2.py", line 369, in _call_chain
result = func(*args)
File "/usr/lib/python2.7/urllib2.py", line 605, in http_error_302
return self.parent.open(new, timeout=req.timeout)
File "/usr/lib/python2.7/urllib2.py", line 397, in open
response = meth(req, response)
File "/usr/lib/python2.7/urllib2.py", line 510, in http_response
'http', request, response, code, msg, hdrs)
File "/usr/lib/python2.7/urllib2.py", line 435, in error
return self._call_chain(*args)
File "/usr/lib/python2.7/urllib2.py", line 369, in _call_chain
result = func(*args)
File "/usr/lib/python2.7/urllib2.py", line 518, in http_error_default
raise HTTPError(req.get_full_url(), code, msg, hdrs, fp)
HTTPError: HTTP Error 502: Bad Gateway

1 Ответ

4 голосов
/ 26 января 2012

Обратите внимание, что urllib2 не поточно-ориентированный . Таким образом, вы действительно должны использовать urllib3 .

Некоторые из ваших проблем совершенно не связаны с многопоточностью. Потоки просто делают сообщения об ошибках более сложными. Вместо

data = urllib2.urlopen(url).read

хочешь

data = urllib2.urlopen(url).read()
#                               ^^

Ошибка 502 Bad gateway указывает на неправильную настройку сервера (скорее всего, внутренний сервер веб-службы, к которой вы подключаетесь, перезагружается / недоступен). С этим ничего не поделаешь - URL сейчас просто недоступен. Используйте try..except для обработки этих ошибок, например, распечатав диагностическое сообщение или запланировав URL-адрес, который необходимо получить после соответствующего периода ожидания, или пропустив сбойный набор данных.

Чтобы получить значения из очереди, вы можете сделать следующее:

res = fetch_parallel()
reslist = []
while not res.empty():
  reslist.append(res.get_nowait()) # or get, doesn't matter here
print (reslist)

Реальная обработка ошибок также невозможна, если URL-адрес действительно недоступен. Простой повторный запрос может работать в некоторых случаях, но вы должны быть в состоянии справиться с ситуацией, когда удаленный хост действительно недоступен в настоящее время. Как вы это сделаете, зависит от логики вашего приложения.

...