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

如何随机打乱csv.DictReader的输出并结合ThreadPoolExecutor实现多线程处理不同行数据

如何随机打乱csv.DictReader的输出并结合ThreadPoolExecutor实现多线程处理不同行数据

我来帮你解决这个问题~你现在遇到的核心问题是每个线程都重复读取了原始顺序的CSV行,所以输出和处理逻辑完全一致。下面给你两种可行的解决方案,分别对应不同的需求场景:

方案一:每个线程独立读取并打乱全行(适合压力测试等重复处理场景)

如果你的需求是让每个线程都遍历所有行,但顺序随机(比如做接口压力测试),可以在每个线程里把读取到的行转成列表后打乱,再进行处理。这样每个线程的行顺序都是随机且不同的:

import csv
import random
from concurrent.futures import ThreadPoolExecutor
import requests

def grab_data(thread_id):
    with open('devices.csv', 'r') as csv_file:
        csv_reader = csv.DictReader(csv_file)
        # 把CSV行转成列表,原地打乱顺序
        rows = list(csv_reader)
        random.shuffle(rows)
        
        # 遍历打乱后的行发送请求
        for line in rows:
            r = requests.get(
                url=f"https://192.168.1.56:1813/rest/{line['A']}/sh/1/sl/{line['B']}/{line['C']}/status?",
                verify=False,
                auth=('random', 'TestTest'),
            )
            # 可选:打印线程ID和处理结果,方便调试
            print(f"线程{thread_id}处理行: {line},响应状态码: {r.status_code}")

with ThreadPoolExecutor(max_workers=5, thread_name_prefix="API") as executor:
    executor.map(grab_data, range(1, 15))

方案二:一次性读取并打乱,分发给线程处理不同子集(适合并行处理无重复场景)

如果你想要所有线程同时处理不同的行(避免重复处理同一行),更高效的方式是先一次性读取所有行并打乱,再分割成多个子集分配给每个线程。这样既避免了重复读取文件,又能保证每个线程处理的是不同的随机行:

import csv
import random
from concurrent.futures import ThreadPoolExecutor
import requests

def process_rows(thread_id, rows_subset):
    # 处理分配到的行子集
    for line in rows_subset:
        r = requests.get(
            url=f"https://192.168.1.56:1813/rest/{line['A']}/sh/1/sl/{line['B']}/{line['C']}/status?",
            verify=False,
            auth=('random', 'TestTest'),
        )
        print(f"线程{thread_id}处理行: {line},响应状态码: {r.status_code}")

if __name__ == "__main__":
    # 提前读取所有行并打乱,只做一次更高效
    with open('devices.csv', 'r') as csv_file:
        csv_reader = csv.DictReader(csv_file)
        all_rows = list(csv_reader)
        random.shuffle(all_rows)
    
    max_workers = 5
    # 把打乱后的行分割成对应线程数的子集
    chunk_size = len(all_rows) // max_workers
    row_chunks = []
    for i in range(max_workers):
        start_idx = i * chunk_size
        # 最后一个子集包含剩余所有行,避免遗漏
        end_idx = start_idx + chunk_size if i != max_workers -1 else len(all_rows)
        row_chunks.append(all_rows[start_idx:end_idx])
    
    # 启动线程池分配任务
    with ThreadPoolExecutor(max_workers=max_workers, thread_name_prefix="API") as executor:
        executor.map(process_rows, range(1, max_workers+1), row_chunks)

一些注意事项

  • 记得导入random模块,random.shuffle()会原地打乱列表,不需要额外赋值。
  • 如果你觉得verify=False的不安全警告很烦,可以在代码开头加上这一行关闭警告:
    requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)
    
  • 如果你的CSV文件特别大,第二种方案更节省资源(只读取一次文件),但两种方案都需要将全行加载到内存;如果文件超大到内存放不下,可以考虑分块读取并打乱,但一般业务场景下全行加载是没问题的。

备注:内容来源于stack exchange,提问作者UndyingThanos

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.13 19:42:58