2013-06-12 3 views
0

В настоящее время я тестирую что-то с Threading/workpool; Я создаю 400 потоков, которые загружают в общей сложности 5000 URLS ... Проблема в том, что некоторые из 400 потоков «замораживаются», при просмотре моих процессов я вижу, что + - 15 потоков при каждом запуске замерзают, а через некоторое время close 1 by 1.Python Нити не заканчиваются

Мой вопрос в том, есть ли способ иметь какой-то «таймер»/«счетчик», который убивает поток, если он не закончен через х секунд.

# download2.py - Download many URLs using multiple threads. 
import os 
import urllib2 
import workerpool 
import datetime 
from threading import Timer 

class DownloadJob(workerpool.Job): 
    "Job for downloading a given URL." 
    def __init__(self, url): 
     self.url = url # The url we'll need to download when the job runs 
    def run(self): 
     try: 
      url = urllib2.urlopen(self.url).read() 
     except: 
      pass 

# Initialize a pool, 400 threads in this case 
pool = workerpool.WorkerPool(size=400) 

# Loop over urls.txt and create a job to download the URL on each line 
print datetime.datetime.now() 
for url in open("urls.txt"): 
    job = DownloadJob(url.strip()) 
    pool.put(job) 

# Send shutdown jobs to all threads, and wait until all the jobs have been completed 
pool.shutdown() 
pool.wait() 
print datetime.datetime.now() 
+4

вы проводили какой-то анализ, чтобы увидеть, является ли 400 нитей на самом деле улучшения вашей работы? Темы не являются бесплатными; есть некоторые накладные расходы, связанные с каждым потоком, и идеальное количество потоков может быть намного меньше. –

ответ

0

urlopen принимает значение таймаута, это был бы лучший способ справиться с этим.

Но я согласен с комментатором, что 400 нитей, вероятно, слишком много

+0

Я попытался выяснить, сколько времени потребовалось для обработки этих 5000 URL-адресов с потоками 5, 100, 200 и 400. + - 200 был самым быстрым. – Coryza

1

The problem is that some of the 400 threads are "freezing"...

Это, скорее всего, из-за эту линию ...

url = urllib2.urlopen(self.url).read() 

По умолчанию, Python будет ждать вечно удаленный сервер, чтобы ответить, поэтому, если один из ваших URL указывает на сервер, который игнорирует пакет SYN, или иначе просто действительно медленно, поток потенциально может быть заблокирован навсегда.

Вы можете использовать параметр timeout из urlopen() установить предел, как долго поток будет ждать удаленного хоста, чтобы ответить ...

url = urllib2.urlopen(self.url, timeout=5).read() # Time out after 5 seconds 

... или вы можете установить его в глобальном масштабе, а не с socket.setdefaulttimeout(), помещая эти строки в верхней части кода ...

import socket 
socket.setdefaulttimeout(5) # Time out after 5 seconds 
+0

Это сработало отлично! Большое спасибо. Однако, когда я это сделаю, URL-адрес никогда не будет загружен, какой код я должен добавить, чтобы URL-адрес снова попытался (если возможно, в коротком коде)?) – Coryza

+0

@Coryza Это немного сложнее из-за многопоточной природы кода. Быстрый взломам будет иметь глобальный список и добавить URL-адрес в список в блоке 'except' (поскольку добавление списка является потокобезопасным). Как только 'pool.wait()' возвращает, вы можете либо повторить неудавшийся список, либо просто выгрузить его в файл, имея в виду, что возможно, что эти URL-адреса могут никогда не работать в будущем. – Aya

+0

Уже боялся этого .. hmmm ... – Coryza

Смежные вопросы