Python多线程批量发送POST请求重复执行问题的修复咨询
修复Python多线程批量处理文件时条目重复执行的问题
问题描述
我用Python多线程实现带文件的POST请求,批量处理file.txt中的内容(内容为1、2、3、4、5),计划启用8个线程,示例中写了3个继承Thread的类,用islice给各线程分配行范围,但运行后出现条目重复执行的情况(比如1、2、3多次返回success),希望每个条目仅执行一次(1-5各返回一次success),如何修复?
原代码
import requests import requests as reqs from threading import * from itertools import islice from requests.packages.urllib3.exceptions import InsecureRequestWarning account = "file.txt" loaded = len(open(account, encoding = "ISO-8859-1").readlines()) class check1(Thread): def run(self): with open(account) as lines: for lines in islice(lines, 0, loaded, 8): check(lines) class check2(Thread): def run(self): with open(account) as lines: for lines in islice(lines, 1, loaded, 8): check(lines) class check3(Thread): def run(self): with open(account) as lines: for lines in islice(lines, 2, loaded, 8): check(lines) workers = [check1(), check2(), check3()] for worker in workers: worker.start() for worker in workers: worker.join()
文件内容(file.txt)
1 2 3 4 5
当前运行结果
1 success 1 success 2 success 3 success 2 success 3 success etc
期望结果
1 success 2 success 3 success 4 success 5 success
问题原因
- 步长设置错误:给
islice设置的步长是8,但当前只有3个线程,每个线程会循环取自己起始索引的行(比如线程0一直取第0行,线程1一直取第1行),导致重复执行。 - 线程类冗余:手动创建多个
Thread子类的方式扩展性差,新增线程需要额外写类,容易出错。 - 多线程重复读文件:每个线程单独打开文件读取,既浪费资源,也可能因文件读取位置问题导致重复。
修复方案
修正后的代码
import requests from threading import Thread from itertools import islice from requests.packages.urllib3.exceptions import InsecureRequestWarning # 禁用不安全请求警告 requests.packages.urllib3.disable_warnings(InsecureRequestWarning) account_file = "file.txt" def check(line): # 替换为你的实际POST请求逻辑 print(f"{line.strip()} success") class CheckThread(Thread): def __init__(self, thread_idx, total_threads, lines): super().__init__() self.thread_idx = thread_idx self.total_threads = total_threads self.lines = lines def run(self): # 每个线程处理从自身索引开始、步长为总线程数的行,确保无重叠 for line in islice(self.lines, self.thread_idx, None, self.total_threads): check(line) if __name__ == "__main__": # 提前读取所有行并过滤空行,避免多线程重复打开文件 with open(account_file, encoding="ISO-8859-1") as f: all_lines = [line for line in f if line.strip()] total_threads = 3 # 可修改为你计划的8个线程 workers = [] # 批量创建并启动线程 for idx in range(total_threads): worker = CheckThread(idx, total_threads, all_lines) workers.append(worker) worker.start() # 等待所有线程执行完毕 for worker in workers: worker.join()
改进说明
- 通用线程类:
CheckThread支持任意数量线程,无需手动创建多个子类,扩展性强。 - 任务分配逻辑修正:使用
islice(self.lines, self.thread_idx, None, self.total_threads),每个线程处理的行索引无重叠:- 线程0处理索引0、3、6...
- 线程1处理索引1、4、7...
- 线程2处理索引2、5、8...
- 提前读取文件:仅读取一次文件并过滤空行,避免多线程重复IO操作,提升效率。
- 代码简洁性:去除冗余的
requests重复导入,规范变量命名。
验证结果
运行修正后的代码,会输出:
1 success 2 success 3 success 4 success 5 success
完全符合期望,每个条目仅执行一次。
内容的提问来源于stack exchange,提问作者bymechul
相关产品推荐
相关产品推荐

