2010-09-06 2 views
1

Я написал простой веб-сайт с помощью threadpool. Проблема заключается в следующем: тогда искатель получает по всему сайту, он должен закончить, но в действительности он ждет чего-то в конце, а скрипт не закончил, почему это произошло?проблема с python threadpool (дождаться чего-то)

from Queue import Queue 
from threading import Thread 

import sys 
from urllib import urlopen 
from BeautifulSoup import BeautifulSoup, SoupStrainer 
import re 
from Queue import Queue, Empty 
from threading import Thread 

visited = set() 
queue = Queue() 

class Worker(Thread): 
    """Thread executing tasks from a given tasks queue""" 
    def __init__(self, tasks): 
     Thread.__init__(self) 
     self.tasks = tasks 
     self.daemon = True 
     self.start() 

    def run(self): 
     while True: 
      func, args, kargs = self.tasks.get() 
      print "startcall in thread",self 
      print args 
      try: func(*args, **kargs) 
      except Exception, e: print e 
      print "stopcall in thread",self 
      self.tasks.task_done() 

class ThreadPool: 
    """Pool of threads consuming tasks from a queue""" 
    def __init__(self, num_threads): 
     self.tasks = Queue(num_threads) 
     for _ in range(num_threads): Worker(self.tasks) 

    def add_task(self, func, *args, **kargs): 
     """Add a task to the queue""" 
     self.tasks.put((func, args, kargs)) 

    def wait_completion(self): 
     """Wait for completion of all the tasks in the queue""" 
     self.tasks.join() 


def process(pool,host,url): 

    try: 
     print "get url",url 
     #content = urlopen(url).read().decode(charset) 
     content = urlopen(url).read() 
    except UnicodeDecodeError: 
     return 

    for link in BeautifulSoup(content, parseOnlyThese=SoupStrainer('a')): 
     #print "link",link 
     try: 
      href = link['href'] 
     except KeyError: 
      continue 


     if not href.startswith('http://'): 
      href = 'http://%s%s' % (host, href) 
     if not href.startswith('http://%s%s' % (host, '/')): 
      continue 



     if href not in visited: 
      visited.add(href) 
      pool.add_task(process,pool,host,href) 
      print href 




def start(host,charset): 

    pool = ThreadPool(7) 
    pool.add_task(process,pool,host,'http://%s/' % (host)) 
    pool.wait_completion() 

start('simplesite.com','utf8') 

ответ

1

Проблема, которую я вижу, что вы никогда не выйти из то время как в перспективе. Таким образом, это будет блок навсегда. Вы должны разорвать этот цикл, когда выполняются задания.

Вы можете попробовать:
1) вставить

if not func: break 

после task.get (...) в перспективе.

2) добавить

pool.add_task(None, None, None) 

в конце процесса .

Это способ для процесса уведомить бассейн, что у него нет больше задач для обработки.

+0

thanx, для справки. Я решаю это, наконец, если self.tasks.qsize() == 0: break – Evg

+0

@Evg: Будьте осторожны: «очередь задач пуста» - это не то же самое, что «больше нечего делать» ... – dugres

+0

yes thnx again) Я понимаю это, это проблема. В вашем случае «в конце процесса». я должен проверить пустую очередь, и если она пуста, пул pool.add_task (None, None, None). Идея сделать это без «задачи остановки» не живет, я думаю, флаг для exsist - все рабочие имеют состояние ожидания (строка до func, args, kargs = self.tasks.get() ). Если это произойдет, я могу сломать все петли у всех рабочих, что вы думаете об этом? – Evg