我正在编写一个小应用程序,以通过http下载文件(例如,此处描述)。
我还想添加一个下载进度指示器,以显示下载进度的百分比。
这是我想出的:
1 2 3 4 5 6 7 8
| sys.stdout.write(rem_file +"...")
urllib.urlretrieve(rem_file, loc_file, reporthook=dlProgress)
def dlProgress(count, blockSize, totalSize):
percent = int(count*blockSize*100/totalSize)
sys.stdout.write("%2d%%" % percent)
sys.stdout.write("\b\b\b")
sys.stdout.flush() |
输出:MyFileName ... 9%
还有其他想法或建议吗?
有点烦人的是,终端上闪烁的光标位于百分比的第一位数。 有办法防止这种情况吗? 有没有隐藏光标的方法?
编辑:
这是在dlProgress中使用全局变量作为文件名和' r'代码的更好选择:
1 2 3 4 5 6 7 8 9
| global rem_file # global variable to be used in dlProgress
urllib.urlretrieve(rem_file, loc_file, reporthook=dlProgress)
def dlProgress(count, blockSize, totalSize):
percent = int(count*blockSize*100/totalSize)
sys.stdout.write("
" + rem_file +"...%d%%" % percent)
sys.stdout.flush() |
输出:MyFileName ... 9%
光标显示在该行的末尾。 好多了。
在http://pypi.python.org/pypi/progressbar/2.2上有一个适用于python的文本进度条库,您可能会觉得有用:
This library provides a text mode progressbar. This is tipically used to display the progress of a long running operation, providing a visual clue that processing is underway.
The ProgressBar class manages the progress, and the format of the line is given by a number of widgets. A widget is an object that may display diferently depending on the state of the progress. There are three types of widget: - a string, which always shows itself; - a ProgressBarWidget, which may return a diferent value every time it's update method is called; and - a ProgressBarWidgetHFill, which is like ProgressBarWidget, except it expands to fill the remaining width of the line.
The progressbar module is very easy to use, yet very powerful. And automatically supports features like auto-resizing when available.
您也可以尝试:
1 2 3
| sys.stdout.write("
%2d%%" % percent)
sys.stdout.flush() |
在字符串的开头使用单个回车符,而不要使用多个退格键。您的光标仍然会闪烁,但是它将在百分号之后而不是在第一位数字下方闪烁,并且使用一个控制字符而不是三个控制字符,您的闪烁可能会更少。
对于它的价值,这是我用来使其工作的代码:
1 2 3 4 5 6 7 8 9 10
| from urllib import urlretrieve
from progressbar import ProgressBar, Percentage, Bar
url ="http://......."
fileName ="file"
pbar = ProgressBar(widgets=[Percentage(), Bar()])
urlretrieve(url, fileName, reporthook=dlProgress)
def dlProgress(count, blockSize, totalSize):
pbar.update( int(count * blockSize * 100 / totalSize) ) |
如果使用curses包,则可以更好地控制控制台。它还会增加代码复杂性的成本,并且可能是不必要的,除非您正在开发基于控制台的大型应用程序。
对于简单的解决方案,您始终可以将纺车置于状态消息的末尾(字符|, \, -, /的序列实际上在闪烁的光标下看起来不错)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| def download_progress_hook(count, blockSize, totalSize):
"""A hook to report the progress of a download. This is mostly intended for users with slow internet connections. Reports every 5% change in download progress.
"""
global last_percent_reported
percent = int(count * blockSize * 100 / totalSize)
if last_percent_reported != percent:
if percent % 5 == 0:
sys.stdout.write("%s%%" % percent)
sys.stdout.flush()
else:
sys.stdout.write(".")
sys.stdout.flush()
last_percent_reported = percent
urlretrieve(url, filename, reporthook=download_progress_hook) |
我使用以下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| url = (<file location>)
file_name = url.split('/')[-1]
u = urllib2.urlopen(url)
f = open(file_name, 'wb')
meta = u.info()
file_size = int(meta.getheaders("Content-Length")[0])
print"Downloading: %s Bytes: %s" % (file_name, file_size)
file_size_dl = 0
block_sz = 8192
while True:
buffer = u.read(block_sz)
if not buffer:
break
file_size_dl += len(buffer)
f.write(buffer)
status = r"%10d [%3.2f%%]" % (file_size_dl, file_size_dl * 100. / file_size)
status = status + chr(8)*(len(status)+1)
print status,
f.close() |
像往常一样晚到聚会。这是一个支持报告进度的实现,例如核心urlretrieve:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| import urllib2
def urlretrieve(urllib2_request, filepath, reporthook=None, chunk_size=4096):
req = urllib2.urlopen(urllib2_request)
if reporthook:
# ensure progress method is callable
if hasattr(reporthook, '__call__'):
reporthook = None
try:
# get response length
total_size = req.info().getheaders('Content-Length')[0]
except KeyError:
reporthook = None
data = ''
num_blocks = 0
with open(filepath, 'w') as f:
while True:
data = req.read(chunk_size)
num_blocks += 1
if reporthook:
# report progress
reporthook(num_blocks, chunk_size, total_size)
if not data:
break
f.write(data)
# return downloaded length
return len(data) |
那就是我这样做的方式可以为您提供帮助:
https://github.com/mouuff/MouDownloader/blob/master/api/download.py
对于小文件,您可能需要使用以下行,以避免出现疯狂的百分比:
sys.stdout.write(" r%2d %%"%%)
sys.stdout.flush()
干杯