1、在运行爬虫脚本的时候,发起请求的时候可以直接使用协程发起,但是如果并发执行模块的时候,多线程还是有需要的必要
2、为什么要使用生成器呢?因为单个脚本单机并发,没必要使用mq,队列也比较重一些,并且队列执行涉及到结束轮询的时机问题,使用生成器就没有这个问题,只要这个生成器还一直在yield,那么它就不会结束,当所有的元素被yield结束后会报错,拦截后就可以实现自动结束当前流程
3、在多线程中使用生成器有什么好处?生成器边yield, 边消费, 这样可以避免指定固定的线程数,有的子线程结束,还有的在持续运行
import time
import threading
import traceback
thread_count = 5
def yield_item_num():
'''
生成器,不断的生成
@return:
'''
count = 0
while count < 50:
time.sleep(1)
yield count
count += 1
def main_in():
'''
主启动函数
'''
goods_id_iter = yield_item_num()
threads = []
for i in range(0, thread_count):
t = threading.Thread(target=get_all_goods, args=(i, goods_id_iter,))
threads.append(t)
for t in threads:
t.setDaemon(True)
t.start()
for t in threads:
# 多线程多join的情况下,依次执行各线程的join方法, 这样可以确保主线程最后退出, 且各个线程间没有阻塞
t.join()
def get_all_goods(i, goods_id_iter):
'''
不停的消费生成器,并执行脚本
'''
while True:
try:
offer_id = next(goods_id_list)
#脚本启动入口
time.sleep(5)
print(f'子线程{i}消费:{offer_id}')
except Exception as ee:
if repr(ee) == 'StopIteration()':
print(f'子线程{i}消费结束')
break
elif repr(ee).find('generator already executing') > -1:
time.sleep(1)
else:
traceback.print_exc()
if __name__ == '__main__':
main_in()