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

Python优化服务器GET请求耗时:多线程集成实现咨询

优化批量GET请求:从单线程到多线程提速

你的问题很典型——单线程处理网络请求时,大部分时间都在等待服务器响应,完全浪费了CPU的空闲时间。用多线程可以让多个请求同时发送,把等待时间利用起来,轻松把耗时从17秒压到5秒以内。下面我直接给你改造后的代码,再一步步解释怎么集成到你的现有逻辑里:

基础多线程实现(直接替换你的代码)

首先,我们用Python标准库的concurrent.futures.ThreadPoolExecutor来管理线程池,它比手动写线程逻辑简单太多,而且安全可靠:

import pandas as pd
import requests
from concurrent.futures import ThreadPoolExecutor

auth_token = 'Wy'
df = pd.read_csv('/instaurls.csv')

# 把原来循环里的请求逻辑封装成单独函数
def fetch_ethnicity(url):
    try:
        # 这里用params参数自动处理URL编码,比字符串拼接更安全
        resp = requests.get(
            'http://predict/ethnicity',
            params={'auth_token': auth_token, 'url': url},
            timeout=5  # 设置5秒超时,避免某个请求卡住拖慢整体
        )
        resp.raise_for_status()  # 主动抛出HTTP错误(比如404、500)
        return {
            'url': url,
            'status_code': resp.status_code,
            'response': resp.json()
        }
    except Exception as e:
        # 捕获所有异常,避免单个请求失败导致整个程序崩溃
        return {
            'url': url,
            'error': str(e)
        }

if __name__ == '__main__':
    # 创建线程池,max_workers可以根据测试调整(IO密集型任务建议10-30)
    with ThreadPoolExecutor(max_workers=20) as executor:
        # 给每个URL提交一个请求任务
        futures = [executor.submit(fetch_ethnicity, row[1]) for row in df.itertuples()]
        
        # 遍历所有任务的结果并打印
        for future in futures:
            result = future.result()
            if 'error' in result:
                print(f"⚠️ URL {result['url']} 请求失败: {result['error']}")
            else:
                print(f"✅ URL {result['url']} 状态码: {result['status_code']}")
                print(f"响应内容: {result['response']}")

关键改动说明:

  1. 封装请求函数:把原来循环里的请求逻辑抽成fetch_ethnicity,这样线程池可以调用这个函数处理每个URL。
  2. 线程池管理:用ThreadPoolExecutor自动创建和回收线程,不用手动处理线程的生命周期。max_workers设20是个不错的起点,你可以根据实际测试调整——太大可能会被目标服务器限流,太小提速效果不明显。
  3. 异常处理:添加了try-except块,确保某个请求失败不会影响其他请求,还能清晰看到错误信息。
  4. URL参数优化:用params参数代替字符串拼接,自动处理URL编码,避免因为URL里有特殊字符导致请求失败。

进阶优化:复用连接池进一步提速

如果基础版本还不够快,可以复用requests.Session来减少TCP握手的开销——每个线程用自己的session,避免线程安全问题:

import pandas as pd
import requests
import threading
from concurrent.futures import ThreadPoolExecutor

auth_token = 'Wy'
df = pd.read_csv('/instaurls.csv')

# 线程本地存储,每个线程有自己的session
thread_local = threading.local()

def get_session():
    if not hasattr(thread_local, "session"):
        thread_local.session = requests.Session()
        # 设置连接池大小,提升连接复用效率
        adapter = requests.adapters.HTTPAdapter(pool_connections=10, pool_maxsize=20)
        thread_local.session.mount('http://', adapter)
    return thread_local.session

def fetch_ethnicity(url):
    session = get_session()
    try:
        resp = session.get(
            'http://predict/ethnicity',
            params={'auth_token': auth_token, 'url': url},
            timeout=5
        )
        resp.raise_for_status()
        return {
            'url': url,
            'status_code': resp.status_code,
            'response': resp.json()
        }
    except Exception as e:
        return {
            'url': url,
            'error': str(e)
        }

if __name__ == '__main__':
    with ThreadPoolExecutor(max_workers=20) as executor:
        futures = [executor.submit(fetch_ethnicity, row[1]) for row in df.itertuples()]
        
        for future in futures:
            result = future.result()
            if 'error' in result:
                print(f"⚠️ URL {result['url']} 请求失败: {result['error']}")
            else:
                print(f"✅ URL {result['url']} 状态码: {result['status_code']}")
                print(f"响应内容: {result['response']}")

这个版本通过复用HTTP连接,能进一步减少请求的延迟,对于大量请求来说效果更明显。

测试建议

  • 先跑基础版本,看看耗时有没有降到5秒以内,如果还不够,再调大max_workers(比如到30)。
  • 如果目标服务器有并发限制,别把线程数设得太高,否则可能会收到429(请求过多)错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:21:57