2010-01-26 23 views
8

Gelen URL'lerin karşıdan yüklenmesi için bir kuyruğu okuyan, ancak urllib2 bir bağlantıyı açtığınızda sistemin askıda kaldığı bir işlem ayarlıyorum.Python Process, urllib2 tarafından engellendi

import urllib2, multiprocessing 
from threading import Thread 
from Queue import Queue 
from multiprocessing import Queue as ProcessQueue, Process 

def download(url): 
    """Download a page from an url. 
    url [str]: url to get. 
    return [unicode]: page downloaded. 
    """ 
    if settings.DEBUG: 
     print u'Downloading %s' % url 
    request = urllib2.Request(url) 
    response = urllib2.urlopen(request) 
    encoding = response.headers['content-type'].split('charset=')[-1] 
    content = unicode(response.read(), encoding) 
    return content 

def downloader(url_queue, page_queue): 
    def _downloader(url_queue, page_queue): 
     while True: 
      try: 
       url = url_queue.get() 
       page_queue.put_nowait({'url': url, 'page': download(url)}) 
      except Exception, err: 
       print u'Error downloading %s' % url 
       raise err 
      finally: 
       url_queue.task_done() 

    ## Init internal workers 
    internal_url_queue = Queue() 
    internal_page_queue = Queue() 
    for num in range(multiprocessing.cpu_count()): 
     worker = Thread(target=_downloader, args=(internal_url_queue, internal_page_queue)) 
     worker.setDaemon(True) 
     worker.start() 

    # Loop waiting closing 
    for url in iter(url_queue.get, 'STOP'): 
     internal_url_queue.put(url) 

    # Wait for closing 
    internal_url_queue.join() 

# Init the queues 
url_queue = ProcessQueue() 
page_queue = ProcessQueue() 

# Init the process 
download_worker = Process(target=downloader, args=(url_queue, page_queue)) 
download_worker.start() 

Başka bir modülden, URL'ler ekleyebilirim ve istediğimde işlemi durdurabilir ve işlemin kapanmasını bekleyebilirim.

import module 

module.url_queue.put('http://foobar1') 
module.url_queue.put('http://foobar2') 
module.url_queue.put('http://foobar3') 
module.url_queue.put('STOP') 
downloader.download_worker.join() 

Sorun ("tepki = urllib2.urlopen (talep)") urlopen kullandığınızda tüm bloke kalmasıdır.

Download() işlevini çağırırsam veya yalnızca İşlemsiz iş parçacıkları kullandığımda sorun olmaz.

cevap

4

Burada sorun urllib2 değil, çoklu işlem modülünün kullanımıdır. Windows altında çoklu işlem modülünü kullanırken, modülünüzü alırken hemen çalışan kod kullanmamalısınız - bunun yerine, bir ana birimi if __name__=='__main__' bloğu içine yerleştirin. "Ana modülün güvenli bir şekilde içe aktarılması" bölümüne bakınız here.

#.... 
def start(): 
    global download_worker 
    download_worker = Process(target=downloader, args=(url_queue, page_queue)) 
    download_worker.start() 

Ve ana modülünde: altişlem oldu

import module 
if __name__=='__main__': 
    module.start() 
    module.url_queue.put('http://foobar1') 
    #.... 

Bunu olmadığı için, her seferinde

Kodunuzdaki için

, indirici modülünde aşağıdaki bu değişikliği yapmak ana kodu tekrar çalıştıracak ve başka bir işlemi başlatacak ve asmaya neden olacaktı.

+0

Windows'u kullanmıyorum, ancak bir start() işlevi kullanma önerisi sorunu çözüyor. Teşekkürler! – Davmuz

İlgili konular