You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python批量下载脚本出现ZeroDivisionError(除零错误)求助

解决urllib下载进度钩子中的ZeroDivisionError问题

嘿,我看到你在批量下载文件时遇到了这个烦人的ZeroDivisionError,其实这是个很常见的小坑——当文件太小、下载速度极快(比如命中本地缓存)时,计算耗时的duration会接近0,甚至直接等于0,导致除法运算出错。另外我还注意到你代码里有几个变量名不一致的问题,也会导致额外的错误,一起帮你搞定了。

问题根源拆解

  1. 除以0错误:当下载完成得太快时,time.time() - start_time的结果会小于0.01秒(甚至为0),直接用它做除数就触发了ZeroDivisionError
  2. 变量名错误:函数参数里的block_size和total_size,后面写成了blockSize和totalSize,这会导致NameError
  3. 全局变量风险:用全局start_time在批量下载时会出现状态混乱,比如前一个文件的时间会干扰下一个文件的进度计算

修复后的完整代码

import urllib.request
import json
import sys
import time

with open('finalsinbin.json') as json_data:
    items = json.load(json_data)

def reporthook(count, block_size, total_size, start_time):
    if count == 0:
        return
    duration = time.time() - start_time
    
    # 核心修复:避免除以0,当耗时极短时直接显示速度为0
    if duration < 0.01:
        speed = 0
        progress_size = count * block_size
    else:
        progress_size = count * block_size
        speed = int(progress_size / (1024 * duration))
    
    # 处理服务器不返回文件大小的情况
    if total_size <= 0:
        percent = 100
    else:
        percent = min(int(progress_size * 100 / total_size), 100)
    
    # 优化显示格式,让进度条更直观
    mb = progress_size / (1024 * 1024)
    sys.stdout.write("\r...%d%%, %.1f MB, %d KB/s, %.1f seconds passed" % 
                     (percent, mb, speed, duration))
    sys.stdout.flush()

def batch(startAt, stopAt):
    a = 0
    for i in items:
        a += 1
        if a < startAt or a > stopAt:
            continue
        num = i['id']
        url = i['url']
        typ = i['type']
        urlfinal = f"{url}/{num}{typ}"
        filename = f"{num}{typ}"
        print(f'[{a}] Descargando el archivo {filename}...')
        # 为每个文件单独初始化start_time,避免全局变量冲突
        task_start_time = time.time()
        # 用lambda把当前任务的start_time传递给钩子函数
        urllib.request.urlretrieve(
            urlfinal, 
            filename, 
            lambda count, bs, ts, st=task_start_time: reporthook(count, bs, ts, st)
        )

batch(1, 100)

关键改进说明

  • 避免除以0:增加了duration < 0.01的判断,当下载耗时极短时直接显示速度为0,完美绕过除法错误
  • 修复变量名问题:统一了block_size和total_size的变量名,再也不会出现NameError
  • 移除全局变量:每个下载任务都有自己独立的task_start_time,通过lambda传递给钩子函数,批量下载时状态不会混乱
  • 兼容未知文件大小:有些服务器不会返回文件总大小,此时直接显示100%完成,避免计算出错
  • 优化显示效果:MB和耗时都保留1位小数,进度条看起来更清晰;用f-string替换老旧的格式化方式,代码更简洁
  • 鲁棒性提升:即使遇到极快的下载任务,脚本也能稳定运行

额外实用建议

考虑到你要下载4365个文件,还有几个可以优化的点:

  • 添加异常捕获:给urlretrieve加上try-except块,处理网络中断、文件权限等错误,避免单个文件下载失败导致整个批量任务终止
  • 实现断点续传:如果下载中断,下次可以从已下载的位置继续,不用重新下载整个文件(urllib本身不支持,需要自己处理请求头的Range字段)
  • 控制下载并发:同步下载4000多个文件会很慢,可以用threading开几个线程并发下载(注意不要开太多,避免被服务器封禁)

内容的提问来源于stack exchange,提问作者pedrovn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:36:53