> Salve a tutta la lista, > una di queste sere mi sono imbattuto nel visualizzare il codice sorgente > di qualche applicazione, e dopo 30 secondi ho deciso di scrivermi già il > mio primo programmino. > Bello anzi bellissimo a dir poco stupendo. > In 11 righe mi sono evitato un mare di lavoro. > Ho deciso di creare una nuova applicazione e questa volta ho deciso di > creare uno spider che avevo fatto in c# in windows e rifarlo in python e > devo dire che tutto funziona alla grande. > Il mio unico problema sta nel fatto che vorrei velocizzare il programma > e quindi renderlo multithreading impostando sempre da riga di comando il > numero di thread che vorrei fare. Mi potete dare qualche consiglio??? > > Grazie a tutti per il lavoro che fate.
Ciao, Come già spiegato anche da Valentino, non sempre "multithreading" implica "più veloce". Ma nel tuo caso è così, caschi bene :) In fondo al messaggio attacco uno script che avevo scritto un po' di tempo fa: usa diversi thread per scaricare una serie di file. Non è uno spider perché la lista di cose da scaricare va specificata all'inizio, ma penso sia chiara la modifica da effettuare: quando un'istanza di Job trova una url "interessante", deve aggiungerla alla lista "DownloadManager.urls" dei compiti da svolgere. Dovresti modificare la signature di Job.__init__ in modo che possa ricevere un puntatore a tutto il download manager (che nome borioso!) anziché al solo callback che notifica dell'avvenuto download: io aggiungerei un metodo DownloadManager.add_job(...) che aggiunga il nuovo job alla lista rispettando il lock. "from util import get_logger" non funzionarà: usa "import logging; logging.getLogger" al suo posto. Tutto il resto dovrebbe funzionare. Spero ti serva di "ispirazione": ci ho messo pochi minuti a scriverlo, ha fatto il suo porco lavoro e in effetti il fatto che in Python si scriva un download manager multi-thread in meno di 100 righe fa la sua figura :) Divertiti! -- Daniele Varrazzo - Develer S.r.l. http://www.develer.com -------8<-------8<-------8<-------8<------- #!/usr/bin/env python # -*- coding: iso-8859-1 -*- """Download a bunch of pdb files taken from pdblist.txt """ # Copyright (C) 2005 by Daniele Varrazzo # $Id: dllib.py 909 2005-05-06 01:05:53Z Daniele $ __version__ = "$Revision: 909 $"[11:-2] import os import sys import threading from sets import Set from urllib2 import urlopen from util import get_logger logger = get_logger("download") class DownloadManager: """Download a set of url contents into local files.""" MAX_THREADS = 10 lock = threading.Lock() def __init__(self, urls): """Create a new `DownloadManager` :Parameters: * `urls` (`list` of 2-`tuples`): each couple (`url`, `file`) will become an asynchronous job and run. """ self.urls = urls logger.info("%d files to download" % len(self.urls)) for i in range(min(self.MAX_THREADS, len(self.urls))): url, filename = self.urls.pop() j = Job(url, filename, self.on_finish) j.start() def on_finish(self, job): self.lock.acquire() if self.urls: logger.info("%d files to go" % len(self.urls)) url, filename = self.urls.pop() j = Job(url, filename, self.on_finish) j.start() self.lock.release() class Job(threading.Thread): """The download of an url's contents. A failed download will be tried `TRYS` times before giving up. """ TRYS = 3 def __init__(self, url, filename, callback): """Create a new `Job`. :Parameters: * `url` (`str`): the url to be retrieved * `filename` (`str`): the file name to be stored * `callback` (callable): the function to be called when the job is finished. The callback signature is ``callback(job)`` where `job` is the caler `Job` instance. """ threading.Thread.__init__(self) self.callback = callback self.url = url self.filename = filename logger.info("%s: job created" % url) def run(self): ok = False filename = self.filename url = self.url for itry in range(self.TRYS): try: fi = urlopen(url) logger.info("%s: url found" % url) try: fo = open(filename, "wb") try: while 1: buffer = fi.read(8192) if not buffer: break fo.write(buffer) finally: fo.close() finally: fi.close() except Exception, exc: logger.warning("%s: error opening: %s" % (url, exc)) # Remove partially downloaded files if os.path.exists(filename): os.remove(filename) else: # Downloaded: don't try further ok = True break if ok: logger.info("%s: download OK" % (url)) else: logger.warning("%s: download FAILED" % (url)) self.callback(self)
_______________________________________________ Python mailing list Python@lists.python.it http://lists.python.it/mailman/listinfo/python