yavaş indirme işlemini iptal Yavaş (15 saniyede 1MB'den az). Bunu nasıl başarabilirim? Böyleben http üzerinden dosya indirme ve urllib kullanarak ilerlemeyi gösteren ve aşağıdaki kod duyuyorum piton
cevap
Bu çalışması gerekir. Gerçek indirme oranını hesaplar ve çok düşükse iptal eder.
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()
Güzel bir, sadece ihtiyacım olan şey, teşekkürler. –
Bunun sadece yavaş bağlantı durumunda çalışacağını unutmayın. Sokete zaman aşımı eklemediğiniz sürece, daha normal bağlantı kesilmez. Aksi halde - Tamam! +1 –
şey: Bunu yapabileceğini,
try_one(downloader,15)
YA:
class Timeout(Exception):
pass
def try_one(func,t=3):
def timeout_handler(signum, frame):
raise Timeout()
old_handler = signal.signal(signal.SIGALRM, timeout_handler)
signal.alarm(t) # triger alarm in 3 seconds
try:
t1=time.clock()
func()
t2=time.clock()
except Timeout:
print('{} timed out after {} seconds'.format(func.__name__,t))
return None
finally:
signal.signal(signal.SIGALRM, old_handler)
signal.alarm(0)
return t2-t1
Eğer zaman aşımına istediğiniz fonksiyon ve zaman çağrı 'try_one' zaman aşımına uğramasına
import socket
socket.setdefaulttimeout(15)
Bu, bilinen boyuttaki küçük dosyaları karşıdan yüklüyorsanız iyi bir çözümdür. Boyutu önceden bilmiyorsanız, 'try_one''a kaç saniye geçeceğini bilmeyeceksiniz. Ve eğer bir 100MB dosyası indiriyorsanız, 'try_one (downloader, 1500)' 1500 saniyeye kadar geçmez. Tercihen, indirme işleminin zamanında tamamlanmayacağından emin olur olmaz çıkılır. – Kevin
Evet, kabul etti. Çözüm için teşekkürler, ancak indirme işleminin belirli bir zaman aşımı içinde tamamlanmamasına bağlı olarak minimum iş akışı eşiğine göre iptal etmek istiyorum. –
@HolyMackerel: sadece 10 saniye aralıklarla demek ve hızını kontrol bir Zaman Aşımı olması raporunuzu kanca değiştirin. Sorun, 0 baytın xfered olduğu ve rapor çengelinizin asla çağrılmadığı asılı bir yükleme. –
HolyMackerel! Aletleri kullan!
import urllib2, sys, socket, time, os
def url_tester(url = "http://www.python.org/ftp/python/2.7.3/Python-2.7.3.tgz"):
file_name = url.split('/')[-1]
u = urllib2.urlopen(url,None,1) # Note the timeout to urllib2...
file_size = int(u.info().getheaders("Content-Length")[0])
print ("\nDownloading: {} Bytes: {:,}".format(file_name, file_size))
with open(file_name, 'wb') as f:
file_size_dl = 0
block_sz = 1024*4
time_outs=0
while True:
try:
buffer = u.read(block_sz)
except socket.timeout:
if time_outs > 3: # file has not had activity in max seconds...
print "\n\n\nsorry -- try back later"
os.unlink(file_name)
raise
else: # start counting time outs...
print "\nHmmm... little issue... I'll wait a couple of seconds"
time.sleep(3)
time_outs+=1
continue
if not buffer: # end of the download
sys.stdout.write('\rDone!'+' '*len(status)+'\n\n')
sys.stdout.flush()
break
file_size_dl += len(buffer)
f.write(buffer)
status = '{:20,} Bytes [{:.2%}] received'.format(file_size_dl,
file_size_dl * 1.0/file_size)
sys.stdout.write('\r'+status)
sys.stdout.flush()
return file_name
Bu, beklendiği gibi bir durum yazdırır. Benim ethernet kablosu prizden, ben alıyorum: Ben kabloyu prizden Eğer
Downloading: Python-2.7.3.tgz Bytes: 14,135,620
827,392 Bytes [5.85%] received
sorry -- try back later
ardından az 12 saniye içinde tekrar takın, alıyorum: Dosya başarıyla yüklenirse
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!
.
Sen urllib2 zaman aşımı ve yeniden bağlanır destekler görebilirsiniz. 3 * 4 saniye == 12 saniye için bağlantıyı keser ve bağlantısız kalırsanız, iyi zaman aşımına uğrayacak ve ölümcül bir istisna oluşturacaktır. Bu da ele alınabilir.
sayesinde, güzel bir çözümdür ama durdu indirmeleri ziyade yavaş indirmeleri yakalar. –
Rapor sayfanızda bir Özel Durum oluşturabilirsiniz. – Tobold
Evet, durum istisna Google'da hızlı bir bakıştan, indirmeyi durdurmak popüler bir yolu olarak görünmektedir. Ancak belgelerde belirtilmemiş, bu da beklenmedik davranışlara sahip olabileceğinden endişe ediyor. Örneğin, veriler özel bir iş parçacığı tarafından alınabilir ve bir istisna atmak onu bir yetim haline getirecek ve aslında yüklemeyi durdurmayacaktır. – Kevin