python进程和线程
python进程和线程
课程参考地址:3小时彻底搞懂Python进程和线程,学不会退出IT界!!_哔哩哔哩_bilibili
第一章 线程和进程的区别
进程和线程
-
现实和程序类比
- 一个工厂,至少有一个车间,一个车间至少有1个工人,最终是工人在工作
- 一个程序,至少有一个进程,一个进程至少有一个线程,最终是线程在工作
-
线程和进程的区别
- 如果只有1个车间,每个车间至少有一个工人,那么代表这是1个进程,该进程里只有一个主线程
- 如果有2个车间,每个车间至少有1个工人,那么代表这是2个进程
- 如果只有1个车间,该车间有2个工人,那么代表这是1个进程,该进程里有2个线程
-
总结
- 每个py文件运行,就是一个进程,如果将该py文件打开2个,那么就是2个进程
- 正常情况下,A.py文件时从头执行到尾的,这是由主线程操作的,也就是代表工程A里只有一个工人
- 比如验证5个url是否存在漏洞,如果是单进程,5线程,就相当于我们请了5个工人来帮我们进行验证,所以只需要1轮就完事了,当然也可以使用5进程,相当于多开5个py脚本,每个py脚本处理一条url,但是多进程会占用电脑资源过多
多进程和多线程对比
- 多进程耗费的资源多,用qq来说,相当于要多开多个qq
- 多线程耗费资源少,完成任务快
多线程模板
-
易错点:传递参数的时候,args括号里面必须要由逗号 ,
-
import requests,time import threading #多线程模块 def scan(ip): res = requests.get(ip) print(time.time()) #线程结束时间,结束时间一定要写在这里,如果写在for循环后面,那样不行,因为那是在主线程打印时间,主线程很快就会结束 with open("targest.txt","r",encoding="utf-8") as f: urls = f.readlines() print(time.time()) #线程开始时间 #这里创建的线程数取决于urls里有多少条目标,如果有50条url,就代表创建了50个线程 for url in urls: #遍历所有目标 t = threading.Thread(target=scan,args=(url,)) #每一轮循环创建一个线程,必须要由逗号 t.start() #启动线程,必须要有 t.join() #主线程在此等待,等待主线程执行完毕 print("程序运行完毕") #print(time.time()) #线程结束时间不能写在这里,因为这在主线程打印时间,主线程很快就会结束
多进程模板:导入的模块不同
-
易错点:因为操作系统操作进程的机制不同。所以在windows里必须要将创建进程的代码写在 if name == 'main': 里面,否则会报错
-
import requests,time import multiprocessing #多进程模块 def scan(ip): res = requests.get(ip) print(time.time()) #进程结束时间,结束时间一定要写在这里,如果写在for循环后面,那样不行,因为那是在主线程打印时间,主线程很快就会结束 with open("targest.txt","r",encoding="utf-8") as f: urls = f.readlines() print(time.time()) #进程开始时间 #这里创建的进程数取决于urls里有多少条目标,如果有50条url,就代表创建了50个进程 for url in urls: #遍历所有目标 t = multiprocessing.Process(target=scan,args=(url)) #每一轮循环创建一个进程,如果传递多个参数,可以args=(xx,xx) t.start() #启动进程,必须要有 #print(time.time()) #进程结束时间不能写在这里,因为这在主线程打印时间,主线程很快就会结束
多进程存在的意义:
- 初一看,多线程耗费资源少,为啥还要用多进程?
- 因为python里有一个GIL锁,这个锁规定,每个cpu里只能由一个进程,所以如果我的笔记本电脑是4核的,也就是相当于4个cpu,那么我如果使用单进程,那么其他的3个cpu就会闲置,但是如果我开启3进程,每个进程里面再开启3线程,那么就是 3*3=9 个工人了
第二章 线程池(推荐)
线程池模板
-
from concurrent.futures import ThreadPoolExecutor #导入线程池模块 def scan(target): print(target) if __name__ == '__main__': pool = ThreadPoolExecutor(10) #创建线程数量为10的线程池 for i in range(100000): #此处也可以遍历url文件 pool.submit(scan,i) #提交任务,多个参数就是,pool.submit(scan,xx,xx) pool.shutdown(True) #等待上面的所有的线程执行完毕,再往下执行,必须要这个 print("所有任务执行完毕") #线程池中的任务全部执行完毕才执行这个,守护进程用的
第三章 进程池(推荐)
进程池模板
-
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor #导入进程池模块 def scan(target): print(target) if __name__ == '__main__': pool = ProcessPoolExecutor(10) #创建进程数量为10的线程池 for i in range(100000): #此处也可以遍历url文件 pool.submit(scan,i) #提交任务,多个参数就是,pool.submit(scan,xx,xx) pool.shutdown(True) #等待上面的所有的进程执行完毕,再往下执行,必须要这个 print("所有任务执行完毕") #进程池中的任务全部执行完毕才执行这个,守护进程用的