urllib2 POST进度监控
我正在通过POST将一个相当大的文件与urllib2上传到服务器端脚本。我想显示一个显示当前上传进度的进度指示器。是否有urllib2提供的钩子或回调允许我监视上传进度?我知道你可以通过连续调用read()方法进行下载,但是我没有看到write()方法,只是将数据添加到请求中。urllib2 POST进度监控
这是可能的,但你需要做的几件事情:
- 伪造出来的urllib2的子系统为传递文件句柄向下至httplib的通过附加
__len__
属性,这使得len(data)
返回正确的尺寸,用于填充Content-Length标头。 - 覆盖文件句柄上的
read()
方法:由于httplib调用read()
您的回调将被调用,让您计算百分比并更新您的进度栏。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)
输出:
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
这可以与任何类似文件的对象的工作,但我已经包裹file
显示它如何能与一个真正的大文件,从工作流盘
我不认为这是可能的,但你可以使用pycurl does have upload/download progress callbacks。
我试图保持它的标准库。这将分发给Windows用户,我不希望他们必须安装额外的东西。 – computergeek6 2011-05-08 03:33:12
那么如果你想出了一些东西,在这里分享:) – zeekay 2011-05-08 03:36:01
poster支持此
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"
为什么你把_len_方法?我没有看到httplib在哪里或者你使用它,目的是什么? – MistahX 2011-06-24 02:30:36
它在'urllib2'' AbstractHTTPHandler.do_request _()'和'httplib HttpConnect._send_request()'中使用,其中调用len()来设置Content-length标头。 –
samplebias
2011-06-24 03:14:42
优雅的解决方案,谢谢! – knutole 2013-05-15 18:55:12