引入multiprocessing优化代理检测速度后,程序仅读取文本文件第一行的问题
多进程读取文件仅能获取第一行的根因
- 核心机制差异:单进程运行时,全局
file对象的文件指针会随着每次readline()调用持续向后偏移,因此可以逐行遍历所有条目;但多进程spawn启动模式下,每个新启动的子进程都会独立拷贝一份主进程的文件对象副本,所有副本的文件指针初始位置都停留在文件开头的0偏移处,不会跟着其他进程的读取操作推进。 - 现有代码的逻辑缺陷:主进程本身没有任何推进文件读取指针的操作,每个子进程执行
proxies = file.readline()时,都会从自己拷贝的文件开头位置读取第一行内容,因此无论启动多少个子进程,读到的永远是文件第一行的代理地址。 - 代码附带的其他风险:当前主进程的无限循环没有退出条件、也没有做进程回收,会无限制拉起子进程耗尽系统资源;多进程同时写
goods.txt时会出现IO竞争导致内容错乱。
改造实现方案
- 调整文件读取逻辑:由主进程在启动子进程前,一次性将全文件的代理条目读入内存列表,不再让子进程共享全局文件对象、依赖文件指针推进读取。
- 替换无限制手动创建进程的写法:使用进程池固定并发数提交检测任务,避免系统资源被瞬间占满。
- 替换手动打开/关闭文件的写法:使用
with上下文管理器管理文件句柄,避免资源泄漏;在文件写入环节做兼容处理,避免多进程并发写冲突。
参考改造代码
import requests import multiprocessing from multiprocessing import Pool kind = 'socks4' # 根据机器性能调整并发进程数,不建议超过CPU核心数*2 CONCURRENCY = 8 def check(proxy): # 过滤空行 proxy = proxy.strip() if not proxy: return proxies = { 'http': f'{kind}://{proxy}', 'https': f'{kind}://{proxy}' } target_url = 'http://checkip.dyndns.com/' try: response = requests.get(target_url, timeout=2.5, proxies=proxies) except requests.exceptions.Timeout: print('Bad', proxy) except requests.exceptions.ConnectionError: print('Network problem', proxy) else: print('Good', proxy, 'Response time', response.elapsed) # 用上下文管理器管理输出文件句柄 with open('goods.txt', 'a+') as f: f.write(f'\n{proxy}') if __name__ == '__main__': # 主进程一次性读完全部代理条目,完成文件读取逻辑 with open('SOCKS4.txt', 'r') as f: proxy_list = [line.strip() for line in f.readlines() if line.strip()] # 用进程池分发检测任务 with Pool(processes=CONCURRENCY) as pool: pool.map(check, proxy_list)
内容的提问来源于stack exchange,提问作者Rebirth
相关产品推荐
相关产品推荐

