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

Python使用while loop下载PDF时循环停止但进程仍运行问题求助

核心问题原因

  • 网络请求未设置超时时间:遇到网络波动、服务器响应慢的异常链接时,请求会无限等待,表现为进程后台挂起无输出,停止执行的次数不固定是因为随机碰到了这类异常链接
  • 代码存在逻辑错误:请求状态码非200的分支中,你先执行了i += 1再写入当前i对应的信息,会导致记录的结果和实际请求的链接错位,极端情况会触发列表索引越界
  • 冗余混用requests和urllib两个网络请求库,不必要的逻辑叠加增加了出错概率
  • 缺少网络异常捕获:遇到连接超时、DNS解析失败、链接无效这类非HTTP状态码错误时,代码会直接抛出异常终止,或是无限等待

修复后代码

import pandas as pd
import csv
import requests
import os

# 提前创建PDF存储目录,避免路径不存在报错
save_dir = '/targetpath/'
if not os.path.exists(save_dir):
    os.makedirs(save_dir)

# 读取链接列表
df = pd.read_csv('Linklist.csv', sep = ';')
url_list = df['URL'].tolist()
name_list = df['Name'].tolist()
# 直接批量转年份为字符串,无需额外循环
Year_date = df['Year'].astype(str).tolist()

max_length = len(url_list)
# 统一请求头,全局复用
headers = {
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Safari/605.1.15'
}

# 用with上下文管理器自动处理文件关闭,避免资源泄漏
with open('results.csv', 'w', encoding='utf-8', newline='') as f:
    writer = csv.writer(f)
    # 直接用for循环遍历,无需手动维护计数变量i
    for i in range(max_length):
        current_url = url_list[i]
        current_name = name_list[i]
        current_year = Year_date[i]
        try:
            # 设置10秒超时,超过时长自动终止当前请求抛出异常,避免无限卡住
            response = requests.get(current_url, headers=headers, timeout=10)
            if response.status_code != 200:
                status = str(response.status_code)
                print(f"{current_name} {current_year} {status}")
                writer.writerow([current_name, current_year, status])
                continue
            # 直接用requests返回的二进制内容写PDF,无需调用urllib
            file_path = f"{save_dir}{current_name}{current_year}.pdf"
            with open(file_path, 'wb') as pdf_file:
                pdf_file.write(response.content)
            status = '200'
            print(f"{current_name} {current_year} {status}")
            writer.writerow([current_name, current_year, status])
        # 捕获所有网络相关异常,保证循环不会中断
        except Exception as e:
            status = f"ERROR:{str(e)}"
            print(f"{current_name} {current_year} {status}")
            writer.writerow([current_name, current_year, status])

可选优化建议

  • 可以给失败的请求增加重试机制,比如设置最多重试3次,减少临时网络波动导致的下载失败
  • 下载量较大时可以在两次请求之间加1-3秒的随机延迟,避免请求频率过高被目标站点封禁IP

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 01:15:05