Python进度条和下载

use*_*549 52 python python-2.7

我有一个python脚本,它启动一个可下载文件的URL.有没有办法让python使用命令行显示下载进度而不是启动浏览器?

End*_*age 80

针对您的示例网址进行了更新:

我刚刚写了一个超级简单(略微hacky)的方法,用于从某个站点抓取pdfs.注意,它只能在基于unix的系统(linux,mac os)上正常工作,因为powershell不处理"\ r \n"

import requests

link = "http://indy/abcde1245"
file_name = "download.data"
with open(file_name, "wb") as f:
        print "Downloading %s" % file_name
        response = requests.get(link, stream=True)
        total_length = response.headers.get('content-length')

        if total_length is None: # no content length header
            f.write(response.content)
        else:
            dl = 0
            total_length = int(total_length)
            for data in response.iter_content(chunk_size=4096):
                dl += len(data)
                f.write(data)
                done = int(50 * dl / total_length)
                sys.stdout.write("\r[%s%s]" % ('=' * done, ' ' * (50-done)) )    
                sys.stdout.flush()
Run Code Online (Sandbox Code Playgroud)

它使用请求库,因此您需要安装它.这会在控制台中输出如下内容:

>下载download.data

> [=============]

脚本中的进度条宽度为52个字符(2 []个字符就是进度的50个字符).每个=代表下载量的2%.

  • 您可能希望在iter_content中定义chunk_size,因此它不会那么慢. (2认同)
  • 正如@ 0942v8653所提到的,iter_content()接受一个chunk_size,因此你可以指定它的速度,但是如果你下载的内容足够小,大约1%的内容可以适合内存,你可以通过chunk_size简化你的代码. = total_length/100并且循环的每次迭代将是您下载的1% (2认同)
  • 在 Windows 上为我工作。还将一行从 `for data in response.iter_content():` 更改为 `for data in response.iter_content(chunk_size=total_length/100):`。 (2认同)

Ric*_*nes 58

你可以使用' clint '包(由同一作者写成'requests')为你的下载添加一个简单的进度条,如下所示:

from clint.textui import progress

r = requests.get(url, stream=True)
path = '/some/path/for/file.txt'
with open(path, 'wb') as f:
    total_length = int(r.headers.get('content-length'))
    for chunk in progress.bar(r.iter_content(chunk_size=1024), expected_size=(total_length/1024) + 1): 
        if chunk:
            f.write(chunk)
            f.flush()
Run Code Online (Sandbox Code Playgroud)

这将为您提供动态输出,如下所示:

[################################] 5210/5210 - 00:00:01
Run Code Online (Sandbox Code Playgroud)

它也应该在多个平台上运行!您还可以使用.dots和.mill而不是.bar将条形更改为点或旋转器.

请享用!

  • 克林特现已停产 (4认同)
  • 如果这可以成为python标准库的一部分,那将会很棒. (2认同)

kek*_*ler 15

我很惊讶tqdm没有被建议!在此输入图像描述

  • 如果您提供了一些可以提供有关如何在此上下文中使用tqdm的代码,那么您的答案将得到改进. (20认同)

Chr*_*ute 12

带有TQDM的Python 3

这是TQDM文档中建议的技术。

import urllib.request

from tqdm import tqdm


class DownloadProgressBar(tqdm):
    def update_to(self, b=1, bsize=1, tsize=None):
        if tsize is not None:
            self.total = tsize
        self.update(b * bsize - self.n)


def download_url(url, output_path):
    with DownloadProgressBar(unit='B', unit_scale=True,
                             miniters=1, desc=url.split('/')[-1]) as t:
        urllib.request.urlretrieve(url, filename=output_path, reporthook=t.update_to)
Run Code Online (Sandbox Code Playgroud)

  • 这是迄今为止最好的一个。 (4认同)

Yan*_*ong 11

有一个带有requeststqdm的答案。

import requests
from tqdm import tqdm


def download(url: str, fname: str):
    resp = requests.get(url, stream=True)
    total = int(resp.headers.get('content-length', 0))
    with open(fname, 'wb') as file, tqdm(
        desc=fname,
        total=total,
        unit='iB',
        unit_scale=True,
        unit_divisor=1024,
    ) as bar:
        for data in resp.iter_content(chunk_size=1024):
            size = file.write(data)
            bar.update(size)
Run Code Online (Sandbox Code Playgroud)

要点:https : //gist.github.com/yanqd0/c13ed29e29432e3cf3e7c38467f42f51


小智 11

另一个不错的选择是wget

import wget
wget.download('http://download.geonames.org/export/zip/US.zip')
Run Code Online (Sandbox Code Playgroud)

输出将如下所示:

11% [........                                     ] 73728 / 633847
Run Code Online (Sandbox Code Playgroud)

来源:https ://medium.com/@petehouston/download-files-with-progress-in-python-96f14f6417a2


小智 5

我认为您也可以使用click,它也有一个不错的进度栏库。

import click
with click.progressbar(length=total_size, label='Downloading files') as bar:
    for file in files:
        download(file)
        bar.update(file.size)
Run Code Online (Sandbox Code Playgroud)

请享用 !

  • @MortenB是吗?我在3.6.1上收到“ ModuleNotFoundError:没有名为“ click”的模块”。 (3认同)
  • @AbdealiJK 第三方 (2认同)

cas*_*dcl 5

抱歉迟到了答复;刚刚更新了tqdm文档:

https://github.com/tqdm/tqdm/#hooks-and-callbacks

使用urllib.urlretrieve和面向对象:

import urllib
from tqdm.auto import tqdm

class TqdmUpTo(tqdm):
    """Provides `update_to(n)` which uses `tqdm.update(delta_n)`."""
    def update_to(self, b=1, bsize=1, tsize=None):
        """
        b  : Blocks transferred so far
        bsize  : Size of each block
        tsize  : Total size
        """
        if tsize is not None:
            self.total = tsize
        self.update(b * bsize - self.n)  # will also set self.n = b * bsize

eg_link = "https://github.com/tqdm/tqdm/releases/download/v4.46.0/tqdm-4.46.0-py2.py3-none-any.whl"
eg_file = eg_link.split('/')[-1]
with TqdmUpTo(unit='B', unit_scale=True, unit_divisor=1024, miniters=1,
              desc=eg_file) as t:  # all optional kwargs
    urllib.urlretrieve(
        eg_link, filename=eg_file, reporthook=t.update_to, data=None)
    t.total = t.n
Run Code Online (Sandbox Code Playgroud)

或使用requests.get和文件包装器:

import requests
from tqdm.auto import tqdm

eg_link = "https://github.com/tqdm/tqdm/releases/download/v4.46.0/tqdm-4.46.0-py2.py3-none-any.whl"
eg_file = eg_link.split('/')[-1]
response = requests.get(eg_link, stream=True)
with tqdm.wrapattr(open(eg_file, "wb"), "write", miniters=1,
                   total=int(response.headers.get('content-length', 0)),
                   desc=eg_file) as fout:
    for chunk in response.iter_content(chunk_size=4096):
        fout.write(chunk)
Run Code Online (Sandbox Code Playgroud)

你当然可以混合和匹配技术。