杨记

碎片化学习令人焦虑,系统化学习使人进步

0%

多进程


Python这门语言在设计的时候,有一个全局解释器锁(Global Interpreter Lock, GIL)

这导致Python的多线程都是伪多线程,即本质上还是一个线程,但是这个线程每个事情只做几毫秒,几毫秒以后就保存现场,换做其他事情,几毫秒后再做其他事情,一轮之后回到第一件事上,恢复现场再做几毫秒,继续换……微观上的单线程,在宏观上就像同时在做几件事。

这种机制在I/O(Input/Output,输入/输出)密集型的操作上影响不大,但是在CPU计算密集型的操作上面,由于只能使用CPU的一个核,就会对性能产生非常大的影响。所以涉及计算密集型的程序,就需要使用多进程,Python的多进程不受GIL的影响。

爬虫属于I/O密集型的程序,所以使用多线程可以大大提高爬取效率。

多进程库

multiprocessing本身是Python的多进程库,用来处理与多进程相关的操作。

但是由于进程与进程之间不能直接共享内存和堆栈资源,而且启动新的进程开销也比线程大得多,因此使用多线程来爬取比使用多进程有更多的优势。

multiprocessing下面有一个dummy模块,它可以让Python的线程使用multiprocessing的各种方法。

dummy下面有一个Pool类,它用来实现线程池。

这个线程池有一个map()方法,可以让线程池里面的所有线程都“同时”执行一个函数。

1
2
3
4
5
6
7
from multiprocessing.dummy import Pool
def calc_power2(num):
return num**num
pool = Pool(3)
origin_num = [x for x in range(10)]
result = pool.map(calc_power2, origin_num)
print(f'计算0-9的平方分别为:{result}')

程池的map()方法接收两个参数,第1个参数是函数名,第2个参数是一个列表。

第1个参数仅仅是函数的名字,是不能带括号的。

第2个参数是一个可迭代的对象,这个可迭代对象里面的每一个元素都会被函数clac_power2()接收来作为参数。除了列表以外,元组、集合或者字典都可以作为map()的第2个参数。

欢迎关注我的其它发布渠道