Proceso de Python bloqueado por urllib2

Configuro un proceso que lee una cola para que se descarguen las direcciones URL entrantes, pero cuando urllib2 abre una conexión, el sistema se bloquea.

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() 

Desde otro módulo puedo agregar direcciones URL y, cuando lo desee, puedo detener el proceso y esperar a que se cierre.

 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() 

El problema es que cuando uso urlopen (“response = urllib2.urlopen (solicitud)”) queda todo bloqueado.

No hay ningún problema si llamo a la función download () o cuando uso solo subprocesos sin proceso.

El problema aquí no es urllib2, sino el uso del módulo de multiprocesamiento. Cuando use el módulo de multiprocesamiento en Windows, no debe usar el código que se ejecuta inmediatamente al importar su módulo; en su lugar, coloque las cosas en el módulo principal dentro de un if __name__=='__main__' . Consulte la sección “Importación segura del módulo principal” aquí .

Para su código, haga este cambio siguiendo en el módulo de descarga:

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

Y en el módulo principal:

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

Debido a que no hizo esto, cada vez que se iniciara el subproceso ejecutaría el código principal nuevamente e iniciaría otro proceso, lo que provocaría el locking.