Python之多线程与多进程
? 最近一直在学习爬虫的知识,遇到了很多坎坷也同时学到了很多以往从未接触到的知识和领域。我想,学习的点滴进步就在于遇到一个一个问题然后又一个一个解决中积累起来的吧,乐趣也在于此,引用一句话“谁学谁知道啊”😀。
------引用一句史蒂夫?乔布斯的名言:生活不会突变,你要做的只是耐心和积累。人这一辈子没法做太多事情,所以每一件都要做得精彩绝伦。
下面进入正题,目前爬虫技术已经应用非常广泛。当爬取数据量非常大时,就要考虑如何提高爬虫效率。如果使用单线程的爬虫,爬取数据的速度是非常慢的。那么解决的办法就是使用Python中的多线程和多进程,这样就可以实现同时完成多项工作,提高执行效率。
1.1 进程与线程
1.1.1 什么是进程
? 在了解进程之前,我们有必要知道多任务多概念。多任务,顾名思义,就是指操作系统能够执行多个任务。像我们使用Windows和Linux操作系统可以同时看电影、打字、查看网页等等,这就是操作系统在执行多任务,而每一个任务就是一个进程。我以Mac系统为例,查看进程
ps -ef | grep 进程名
liuxiaowei@MacBookAir ~ % ps -ef | grep 3306
501 5102 854 0 5:45PM ttys000 0:00.00 grep 3306
liuxiaowei@MacBookAir ~ $sudo lsof -i
上图中显示的进程只是一部分截图,包括电脑运行的各种应用程序。进程(Process)
1.1.2 什么是线程
线程(Thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程可以并发多个线程,每条线程并行执行不同的任务。这可以打个比方:视频播放这个进程中,显示视频用一个线程,播放音频是一个线程。只有两个线程同时工作,我们才能正常观看画面和声音同步的视频。进程好比一列火车,而线程好比车厢,线程需要在进程下进行,就好比单独的车厢无法行驶一样。一个进程可以包含很多线程,就像火车有很多车厢一样。
1.2创建线程
Python语言内置多线程支持,它的标准库提供了两个模块:_thread和threading, _thread是低级模块,threading是高级模块,对 _thread进行封装。绝大多数情况我们只使用threading这个高级模块。
1.2.1 使用threading模块创建线程
import threading,time
def process():
for i in range(5):
time.sleep(1)
print("thread name is %s" % threading.current_thread().name)
if __name__ == "__main__":
print("------主线程开始-----")
threads = [threading.Thread(target=process) for i in range(4)]
for t in threads:
t.start()
for t in threads:
t.join()
print("-----主线程结束-----")
上述代码中,创建了4个线程,然后分别用for循环执行4次start()和join()方法。每个字线程分别执行5次。运行结果如下:
注:从中可以看出线程的执行顺序是不确定的
1.2.2 使用Thread子类创建线程
import threading
import time
class SubThread(threading.Thread):
def run(self):
for i in range(3):
time.sleep(1)
msg = "子线程" + self.name + "执行,i=" + str(i)
print(msg)
if __name__ == "__main__":
print("------主线程------")
t1 = SubThread()
t2 = SubThread()
t1.start()
t2.start()
t1.join()
t2.join()
print("------主线程结束------")```
1.3 创建进程
1.3.1创建进程的常用方式
1.3.1.1 使用multiprocessing模块创建进程
from multiprocessing import Process
def test(interval):
print('我是子进程')
def main():
print("主进程开始")
p = Process(target = test, args = (1, ))
p.start()
print('主进程结束')
if __name__ == '__main__':
main()
1.3.1.2 使用Process子类创建进程
from multiprocessing import Process
import time
import os
class SubProcess(Process):
def __init__(self, interval, name = ''):
Process.__init__(self)
self.interval = interval
if name:
self.name = name
def run(self):
print("子进程(%s) 开始执行, 父进程为(%s) "%(os.getpid(),os.getppid()))
t_start = time.time()
time.sleep(self.interval)
t_stop = time.time()
print("子进程(%s)执行结束,耗时%0.2f秒"%(os.getpid(),t_stop-t_start))
if __name__ == "__main__":
print("-----父进程开始执行------")
print("父进程PID: %s" %os.getpid())
p1 = SubProcess(interval=1, name='mrsoft')
p2 = SubProcess(interval=2)
p1.start()
p2.start()
print("p1.is_alive=%s"%p1.is_alive())
print("p2.is_alive=%s"%p2.is_alive())
print("p1.name=%s"%p1.name)
print("p1.pid=%s"%p1.pid)
print("p2.name=%s"%p2.name)
print("p2.pid=%s"%p2.pid)
print("-------等待子进程-------")
p1.join()
p2.join()
print("-------父进程执行结束-------")
1.3.1.3 使用进程池Pool创建进程
from multiprocessing import Pool
import os, time
def task(name):
print('子进程 (%s)执行task %s ...' %(os.getpid(), name))
time.sleep(1)
if __name__ == '__main__':
print('父进程(%s) .' %os.getpid())
p = Pool(3)
for i in range(10):
p.apply_async(task, args=(i,))
print('等待所有子进程结束...')
p.close()
p.join()
print('所有子进程结束.')
关于进程和线程还有很多方法和属性,还有进程间通信,线程间通信等等。这就是我的一点学习经历,整理出来跟大家分享。***如果文中出现了错误,请大家帮忙斧正,不吝赐教。***欢迎转发、收藏、点赞。
|