当前位置: 首页 > 知识库问答 >
问题:

PycURL附件和进度函数

杜志
2023-03-14

使用API处理一个小项目,您可以向该API发送请求,然后它会返回一个带有zip文件的响应,您可以下载该文件。我的第一次自动化下载尝试使用setopt(curl.WRITEDATA,fp)函数,但每次尝试都会导致Python脚本崩溃。然后,我改变了策略,使用WRITEFUNCTION将数据写入缓冲区,然后将数据写入一个工作稳定的文件。

这一切都很好,但后来我想添加一个进度条,看看文件下载了多少,并给出一些用户反馈等。这就是事情开始变得奇怪的地方,因为现在进度条在一秒钟内达到100%,zip文件还没有完成下载。当我修改了我的进度函数,只打印下载文件的大小时,它报告了大约100字节的数量(比zip文件小得多)。是否可以使用pycurl(以及下面的curl)中的函数来跟踪附件下载的进度,而不是请求本身?

另外,如果有人能帮助解决WRITEDATA问题,我想这两个问题可能是相互关联的。

共有2个答案

贺方伟
2023-03-14

对于@Elliot G.tqdm的答案,我们应该只得到一个标题,而不是像这样的整个身体;

# show progress % and amount in bytes
r = requests.head(url)   # <==============================
total_size = int(r.headers.get('content-length', 0))
block_size = 1024

由于缺乏声誉,我无法对@Elliot G.的回答发表评论,所以我发布了这篇文章。

束志业
2023-03-14

以下代码将使用pycurl下载一个文件,并显示当前进度(文本):

import pycurl
# for displaying the output text
from sys import stderr as STREAM

# replace with your own url and path variables
url = "http://ovh.net/files/100Mb.dat"
path = 'test_file.dat'

# use kiB's
kb = 1024

# callback function for c.XFERINFOFUNCTION
def status(download_t, download_d, upload_t, upload_d):
    STREAM.write('Downloading: {}/{} kiB ({}%)\r'.format(
        str(int(download_d/kb)),
        str(int(download_t/kb)),
        str(int(download_d/download_t*100) if download_t > 0 else 0)
    ))
    STREAM.flush()

# download file using pycurl
with open(path, 'wb') as f:
    c = pycurl.Curl()
    c.setopt(c.URL, url)
    c.setopt(c.WRITEDATA, f)
    # display progress
    c.setopt(c.NOPROGRESS, False)
    c.setopt(c.XFERINFOFUNCTION, status)
    c.perform()
    c.close()

# keeps progress onscreen after download completes
print()

输出应该是这样的:

Downloading: 43563/122070 kiB (35%)

如果您想使用实际的进度条,也可以这样做。但这需要更多的工作。

以下代码使用tqdm包生成进度条。它在文件下载时实时更新,还显示下载速度和估计剩余时间。由于tqdm工作方式的限制,还需要请求包。这也与total\u dl\u d变量是数组而不是整数的原因有关。

import pycurl
# needed to predict total file size
import requests
# progress bar
from tqdm import tqdm

# replace with your own url and path variables
url = "http://ovh.net/files/10Mb.dat"
path = 'test_file.dat'

# show progress % and amount in bytes
r = requests.get(url)
total_size = int(r.headers.get('content-length', 0))
block_size = 1024

# create a progress bar and update it manually
with tqdm(total=total_size, unit='iB', unit_scale=True) as pbar:
    # store dotal dl's in an array (arrays work by reference)
    total_dl_d = [0]
    def status(download_t, download_d, upload_t, upload_d, total=total_dl_d):
        # increment the progress bar
        pbar.update(download_d - total[0])
        # update the total dl'd amount
        total[0] = download_d

    # download file using pycurl
    with open(path, 'wb') as f:
        c = pycurl.Curl()
        c.setopt(c.URL, url)
        c.setopt(c.WRITEDATA, f)
        # follow redirects:
        c.setopt(c.FOLLOWLOCATION, True)
        # custom progress bar
        c.setopt(c.NOPROGRESS, False)
        c.setopt(c.XFERINFOFUNCTION, status)
        c.perform()
        c.close()

解释所述问题的可能原因:

(问题中没有提供代码,因此我必须猜测一下究竟是什么导致了上述问题…)

基于变量名(fp文件路径
文件写入(WRITEDATA)问题可能是由于提供了文件路径(str)而不是文件对象(io.BufferedWriter)。

根据我自己的经验
在文件下载过程中反复调用XFERINFOFUNCTION回调函数。回调仅提供总文件大小和已下载的总文件大小作为参数。它不计算自上次调用以来的增量(差异)。进度条中描述的问题(“进度条在一秒钟内达到100%,zip文件尚未完成下载”)可能是由于当预计增量时,总下载量(下载量)被用作更新量。如果进度条每次按总下载量递增,那么它将不会反映实际下载量。它将显示出更大的数量。然后,它将超过100%,并出现各种故障。

来源:

  • Pycurl文档(关于回调)
  • PyPi上的TQDM(进度条)包
  • 通过http和请求下载文件时的进度条
 类似资料:
  • PycURL是 libcurl API 之上的一个薄层,PycURL 速度非常快。使用 PycURL,您可以使用 libcurl 库开发 Python 应用程序。

  • 在用户可以查看并与内容进行交互之前,尽可能地减少视觉上的变化,尽量使应用加载过程令人愉快。每次操作只能由一个活动指示器呈现,例如,对于刷新操作,你不能即用刷新条,又用动态圆圈来指示。 指示器类型 在操作中,对于完成部分可以确定的情况下,使用确定的指示器,他们能让用户对某个操作所需要的时间有个快速的了解。 在操作中,对于完成部分不确定的情况下,用户需要等待一定的时间,无需告知后用户台的情况以及所需时

  • 进度事件的种类 进度事件用来描述资源加载的进度,主要由 AJAX 请求、<img>、<audio>、<video>、<style>、<link>等外部资源的加载触发,继承了ProgressEvent接口。它主要包含以下几种事件。 abort:外部资源中止加载时(比如用户取消)触发。如果发生错误导致中止,不会触发该事件。 error:由于错误导致外部资源无法加载时触发。 load:外部资源加载成功时

  • ⚠️每个进度事件都会触发更改检测。

  • Progress Events 规范是W3C 的一个工作草案,定义了与客户端服务器通信有关的事件。这些事件最早其实只针对XHR 操作,但目前也被其他API 借鉴。有以下6 个进度事件。 loadstart:在接收到响应数据的第一个字节时触发。 progress:在接收响应期间持续不断地触发。 error:在请求发生错误时触发。 abort:在因为调用abort()方法而终止连接时触发。 load:

  • 附录B. 函数 在我写作本书的时候,http://php.net/quickref.php列出了共3917个函数,其中包括一些类似函数的语法结构,在此我不准备把它们从函数中区分开来,而是把它作为函数看待。 由于函数数量很大,一一说明它们的正确及安全用法是不太可能的。在此我选出了我认为最需要注意的函数。选择的标准包括使用的频繁度、使用时的危险(安全)度及我本人的经验。 对于每一个列出的函数,我都会提