2010-11-09 19 views
2

Je suis en train d'écrire un client FTP en utilisant Twisted qui télécharge beaucoup de fichiers et j'essaye de le faire assez intelligemment. Cependant, j'ai eu le problème que je vais télécharger plusieurs fichiers très rapidement (parfois ~ 20 par lot, parfois ~ 250) et puis le téléchargement va se bloquer, seulement pour éventuellement avoir des délais de connexion, puis le téléchargement et le début de blocage encore une fois. J'utilise un DeferredSemaphore pour télécharger seulement 3 fichiers à la fois, mais je soupçonne maintenant que ce n'est probablement pas la bonne façon d'éviter d'étrangler le serveur.Comment mettre en file d'attente des commandes FTP dans Twisted?

Voici le code en question:

def downloadFiles(self, result, directory): 
    # make download directory if it doesn't already exist 
    if not os.path.exists(directory['filename']): 
     os.makedirs(directory['filename']) 

    log.msg("Downloading files in %r..." % directory['filename']) 

    files = filterFiles(None, self.fileListProtocol) 
    # from http://stackoverflow.com/questions/2861858/queue-remote-calls-to-a-python-twisted-perspective-broker/2862440#2862440 
    # use a DeferredSemaphore to limit the number of files downloaded simultaneously from the directory to 3 
    sem = DeferredSemaphore(3) 
    jobs = [sem.run(self.downloadFile, f, directory) for f in files] 
    d = gatherResults(jobs) 
    return d 

def downloadFile(self, f, directory): 
    filename = os.path.join(directory['filename'], f['filename']).encode('ascii') 
    log.msg('Downloading %r...' % filename) 
    d = self.ftpClient.retrieveFile(filename, FTPFile(filename)) 
    return d 

Vous remarqué que je réutilisant une connexion FTP (active, en passant) et en utilisant mon propre instance FTPFile pour vous assurer que l'objet fichier local se ferme lorsque la connexion de téléchargement de fichier est «perdue» (c'est-à-dire terminée). En regardant FTPClient Je me demande si je devrais utiliser queueCommand directement. Pour être honnête, je me suis perdu en suivant la commande retrieveFile pour _openDataConnection et au-delà, alors peut-être que c'est déjà utilisé.

Des suggestions? Merci!

Répondre

1

Je suggérerais d'utiliser queueCommand, comme vous l'avez suggéré je suspecte que le sémaphore que vous utilisez est probablement vous causant des problèmes. Je crois que l'utilisation de fileCommand limitera votre FTPClient à une seule connexion active (bien que je ne fasse que spéculer), vous pouvez donc penser à créer quelques instances FTPClient et leur passer des tâches de téléchargement si vous voulez faire les choses rapidement. Si vous utilisez queueStringCommand, vous obtenez un différé que vous pouvez utiliser pour déterminer l'emplacement de chaque client et même ajouter un autre travail à la file d'attente pour ce client dans le rappel.