2011-05-08 18 views
10

Urllib2 ile oldukça büyük bir dosyayı POST aracılığıyla bir sunucu tarafı komut dosyasına yüklüyorum. Mevcut yükleme ilerlemesini gösteren bir ilerleme göstergesi görüntülemek istiyorum. Yükleme ilerlemesini izlememi sağlayan urllib2 tarafından sağlanan bir kanca veya geri çağırma var mı? Bağlantının read() yöntemine yapılan art arda yapılan aramaları kullanarak indirme işlemini yapabileceğinizi biliyorum, ancak write() yöntemini göremiyorum, yalnızca istek üzerine veri ekleyin.urllib2 POST ilerleme izleme

cevap

23

mümkündür ama bir şeyler yapmak gerekir: alışık len(data) dönüşü Doğru boyut kılan bir __len__ niteliği, takılarak bir dosya httplib aşağı kolu geçerek içine urllib2 alt sistem üzerinden

  • Fake İçerik Uzunluğu başlığını doldurun.
  • Dosya tanıtıcınızdaki read() yöntemini geçersiz kıl: https aramaları read() olarak geri çağrınız çağrılır, yüzdeyi hesaplamanıza ve ilerleme çubuğunuzu güncelleştirmenize izin verilir.

    import os, urllib2 
    from cStringIO import StringIO 
    
    class Progress(object): 
        def __init__(self): 
         self._seen = 0.0 
    
        def update(self, total, size, name): 
         self._seen += size 
         pct = (self._seen/total) * 100.0 
         print '%s progress: %.2f' % (name, pct) 
    
    class file_with_callback(file): 
        def __init__(self, path, mode, callback, *args): 
         file.__init__(self, path, mode) 
         self.seek(0, os.SEEK_END) 
         self._total = self.tell() 
         self.seek(0) 
         self._callback = callback 
         self._args = args 
    
        def __len__(self): 
         return self._total 
    
        def read(self, size): 
         data = file.read(self, size) 
         self._callback(self._total, len(data), *self._args) 
         return data 
    
    path = 'large_file.txt' 
    progress = Progress() 
    stream = file_with_callback(path, 'rb', progress.update, path) 
    req = urllib2.Request(url, stream) 
    res = urllib2.urlopen(req) 
    

    Çıktı:

    large_file.txt progress: 0.68 
    large_file.txt progress: 1.36 
    large_file.txt progress: 2.04 
    large_file.txt progress: 2.72 
    large_file.txt progress: 3.40 
    ... 
    large_file.txt progress: 99.20 
    large_file.txt progress: 99.87 
    large_file.txt progress: 100.00 
    

Bu herhangi bir dosya benzeri bir nesne ile işe yarayabilir, ama bu gerçekten büyük bir dosya ile nasıl çalıştıklarını göstermek için file sarılmış ettik diskten akışı

+0

_len_ metodunu neden attınız? Httplib'yi nerede görmüyorum ya da onu kullanıyorsunuz, amaç nedir? – MistahX

+0

Bu urllib2 '' abstractHTTPHandler.do_request _() 've' httplib HttpConnect._send_request() ',' 'Content-length' başlığını ayarlamak için' len () '' çağrısında kullanılır. – samplebias

+0

zarif bir çözüm, teşekkürler! – knutole

1

requests 2.0.0 has streaming uploads. Bu, küçük parçalar oluşturmak ve parçalar arasındaki ilerlemeyi yazdırmak için bir jeneratörü kullanabileceğiniz anlamına gelir.

0

poster Ben standart kütüphaneye tutmaya çalışıyorum bu

import json 
import os 
import sys 
import urllib2 

from poster.encode import multipart_encode 
from poster.streaminghttp import register_openers 

def _upload_progress(param, current, total): 
    sys.stdout.write(
     "\r{} - {:.0f}%    " 
     .format(param.name, 
       (float(current)/float(total)) * 100.0)) 
    sys.stdout.flush() 

def upload(request_resource, large_file_path): 
    register_openers() 
    with open(large_file_path, 'r') as large_file: 
     request_data, request_headers = multipart_encode(
      [('file', largs_file)], 
      cb=_upload_progress) 

     request_headers.update({ 
      'X-HockeyAppToken': 'we use this for hockeyapp upload' 
     }) 

     upload_request = urllib2.Request(request_resource, 
             request_data, 
             request_headers) 
     upload_connection = urllib2.urlopen(upload_request) 
     upload_response = json.load(upload_connection) 
    print "Done"