• python多线程示例


    1. import threading,queue,time
    2. class Thread(threading.Thread):
    3. def __init__(self,name,q):
    4. threading.Thread.__init__(self)
    5. self.name=name
    6. self.q=q
    7. def run(self):
    8. #print('Starting '+self.name)
    9. while self.q.qsize()>0:
    10. print('\r%d/%d'%(lst_length-self.q.qsize(),lst_length),end='') #展示进度
    11. getData(self.q)
    12. #print('Ending '+self.name)
    13. def getData(q):
    14. qu=q.get()
    15. time.sleep(1)
    16. result=(qu,qu**2) #结果可能会乱序,所以此处为元组
    17. results_list.append(result)
    18. def buildQueueAndThreads(lst,threadNum):
    19. workQueue=queue.Queue()
    20. [workQueue.put(i) for i in lst] #构建队列
    21. threads_list=[]
    22. for i in range(1,threadNum+1):
    23. thread=Thread('Thread-'+str(i),q=workQueue)
    24. thread.start()
    25. threads_list.append(thread)
    26. print('\nWaiting for finishing...')
    27. for thread in threads_list: #等待子线程运行完再回到主线程
    28. thread.join()
    29. threadNum=100
    30. lst=list(range(500))
    31. lst_length=len(lst)
    32. start_time=time.time()
    33. results_list=[]
    34. buildQueueAndThreads(lst,threadNum)
    35. print('\n%d 线程处理耗时: %.fs'%(threadNum,time.time()-start_time))
    36. print('result_list length: ',len(results_list))
    37. print(results_list[:5]) #顺序可能会乱,结果为元组的列表
    99/500
    Waiting for finishing...
    499/500
    100 线程处理耗时: 5s
    result_list length:  500
    [(1, 1), (0, 0), (3, 9), (2, 4), (4, 16)]

    有时爬虫程序设置较多线程时,频繁地访问会被服务器拒绝,我们希望为每个线程分配一定数量的任务,当任务数量(尝试爬取次数)达到时即自动结束,这样虽然不能保证数据获取完全,但会随着任务数量的减少,线程数自动减少,从而降低访问频率。未获取完全的部分数据可通过多次运行来实现:

    1. #多线程示例
    2. import threading,queue,time
    3. class Thread(threading.Thread):
    4. def __init__(self,name,q):
    5. threading.Thread.__init__(self)
    6. self.name=name
    7. self.q=q
    8. self.count=0
    9. def run(self):
    10. #print('Starting '+self.name)
    11. while self.q.qsize()>0 and self.count<10 and continue_all_threads:
    12. self.count+=1
    13. print('\r%d/%d continue all threads:%s'%(lst_length-self.q.qsize(),lst_length,continue_all_threads),end='') #展示进度
    14. #print('Ending '+self.name)
    15. def getData(q):
    16. qu=q.get()
    17. time.sleep(1)
    18. result=(qu,qu**2) #结果可能会乱序,所以此处为元组
    19. results_list.append(result)
    20. def buildQueueAndThreads(lst,threadNum):
    21. workQueue=queue.Queue()
    22. [workQueue.put(i) for i in lst] #构建队列
    23. threads_list=[]
    24. for i in range(1,threadNum+1):
    25. thread=Thread('Thread-'+str(i),q=workQueue)
    26. time.sleep(0.1)#延时0.1s,否则进度输出可能不是所期望的结果
    27. thread.start()
    28. threads_list.append(thread)
    29. print('\nWaiting for finishing...')
    30. #for thread in threads_list: #不等子线程结束再进行主线程,主线程与子线程同时进行
    31. # thread.join()
    32. alive_num=threadNum
    33. lst_length=len(lst)
    34. last_workQueue_size=workQueue.qsize()
    35. last_time=time.time()
    36. while alive_num>0:
    37. alive_num=len([t for t in threads_list if t.is_alive()])
    38. workQueue_size=workQueue.qsize()
    39. if workQueue_size
    40. last_workQueue_size=workQueue_size
    41. last_time=time.time()
    42. delta_time=time.time()-last_time
    43. if delta_time>5: #如果超过5s,队列中的任务数量没有减少,则爬取失败,跳出循环。线程函数非爬虫程序,所以此处情况不会发生
    44. break
    45. print('\rAliving num:%d Progress:%d/%d'%(alive_num,lst_length-workQueue.qsize(),lst_length),end='')
    46. global continue_all_threads #此处要声明为全局变量
    47. continue_all_threads=False
    48. threadNum=6
    49. lst=list(range(56))
    50. lst_length=len(lst)
    51. start_time=time.time()
    52. print()
    53. results_list=[]
    54. continue_all_threads=True
    55. buildQueueAndThreads(lst,threadNum)
    56. print('\n%d 线程处理耗时: %.1fs'%(threadNum,time.time()-start_time))
    57. print('result_list length: ',len(results_list))
    58. print(results_list[:5]) #顺序可能会乱,结果为元组的列表
    5/56 continue all threads:True
    Waiting for finishing...
    Aliving num:0 Progress:56/56rue
    6 线程处理耗时: 10.4s
    result_list length:  56
    [(0, 0), (1, 1), (2, 4), (3, 9), (4, 16)]
  • 相关阅读:
    基于混合Transformer-CNN模型的多分辨率学习方法的解剖学标志检测
    【毕业设计】大数据电商销售预测分析 - python 数据分析
    vue3后台管理系统之pinia及持久化集成使用
    div或者div中的内容居中对齐的方法
    【数据标注】Label Studio用于机器学习标注
    【C++ Primer Plus】第3章 处理数据
    OpenJudge NOI题库 1.7 编程基础之字符串
    通信协议:Uart的Verilog实现(上)
    回环设备(/dev/loop*)与losetup命令
    支付分账户系统——新美业连锁的交易数字化破局之道
  • 原文地址:https://blog.csdn.net/csdndscs/article/details/133611864