7
votes

Annuler le téléchargement lent à Python

Je télécharge des fichiers sur http et affichant la progression à l'aide de Urllib et le code suivant - qui fonctionne bien:

import sys
from urllib import urlretrieve

urlretrieve('http://example.com/file.zip', '/tmp/localfile', reporthook=dlProgress)

def dlProgress(count, blockSize, totalSize):
  percent = int(count*blockSize*100/totalSize)
  sys.stdout.write("\r" + "progress" + "...%d%%" % percent)
  sys.stdout.flush()


2 commentaires

Vous pouvez susciter une exception dans votre meeachook.


Ouais, élever une exception semble être le moyen populaire d'arrêter de télécharger, d'un look rapide sur Google. Cela n'est pas mentionné dans la documentation cependant, ce qui me fait craindre que cela puisse avoir un comportement inattendu. Par exemple, peut-être que les données sont extraites par un thread dédié et jetant une exception en créer une orpheline et n'arrête pas réellement le téléchargement.


3 Réponses :


3
votes

quelque chose comme ceci: xxx

l'appel "try_one" avec le fonctionnement que vous voulez titrater et le délai d'attente: xxx < p> ou, vous pouvez le faire: xxx


3 commentaires

C'est une bonne solution si vous téléchargez de petits fichiers de taille connue. Si vous ne connaissez pas la taille à l'avance, vous ne saurez pas combien de secondes à passer à try_one . Et si vous téléchargez un fichier de 100 Mo, try_one (téléchargeur, 1500) n'abandonnera pas avant que 1500 secondes soient écoulées. De préférence, cela quitterait dès qu'il était convaincu que le téléchargement ne finira pas à temps.


Oui, convenu. Merci pour la solution, mais je voudrais annuler en fonction du seuil de débit minimal, non pas si le téléchargement est terminé dans un délai déterminé.


@Holymackerel: Modifiez simplement votre rapport de rapport pour avoir un délai d'attente à 10 secondes et vérifiez le taux. Le problème est un téléchargement suspendu où 0 octets sont xfered et votre code de rapport n'est jamais appelé.



0
votes

Holymackerel! Utilisez les outils!

Downloading: Python-2.7.3.tgz Bytes: 14,135,620
             716,800 Bytes [5.07%] received
Hmmm... little issue... I'll wait a couple of seconds

Hmmm... little issue... I'll wait a couple of seconds
Done! 


1 commentaires

Merci, c'est une belle solution mais cela attrape des téléchargements bloqués plutôt que des téléchargements lents.



4
votes

Cela devrait fonctionner. Il calcule le taux de téléchargement actuel et abandonne s'il est trop bas.

import sys
from urllib import urlretrieve
import time

url = "http://www.python.org/ftp/python/2.7.3/Python-2.7.3.tgz" # 14.135.620 Byte
startTime = time.time()

class TooSlowException(Exception):
    pass

def convertBToMb(bytes):
    """converts Bytes to Megabytes"""
    bytes = float(bytes)
    megabytes = bytes / 1048576
    return megabytes


def dlProgress(count, blockSize, totalSize):
    global startTime

    alreadyLoaded = count*blockSize
    timePassed = time.time() - startTime
    transferRate = convertBToMb(alreadyLoaded) / timePassed # mbytes per second
    transferRate *= 60 # mbytes per minute

    percent = int(alreadyLoaded*100/totalSize)
    sys.stdout.write("\r" + "progress" + "...%d%%" % percent)
    sys.stdout.flush()

    if transferRate < 4 and timePassed > 2: # download will be slow at the beginning, hence wait 2 seconds
        print "\ndownload too slow! retrying..."
        time.sleep(1) # let's not hammer the server
        raise TooSlowException

def main():
    try:
        urlretrieve(url, '/tmp/localfile', reporthook=dlProgress)

    except TooSlowException:
        global startTime
        startTime = time.time()
        main()

if __name__ == "__main__":
    main()


1 commentaires

Notez que cela ne fonctionnera que dans le cas d'une connexion de ralentissement. La connexion abandonnée plus habituelle ne fonctionnera pas à moins que vous ajoutez un délai d'attente à la prise. Sinon - OK! +1