提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
提示:这里可以添加本文要记录的大概内容:
笔记五Python多线程与多进程
提示:以下是本篇文章正文内容,下面案例可供参考
一、Python 多线程
c
# 计算机想要运行一个程序.必须要单独的创建一个进程.
# 进程是一个资源单位..... 它不是执行单位....
# 进程是进行中的程序...
# 进程与进程之间默认情况下是隔离开的.. 除了病毒, 杀毒软件/ 破坏性的程序.
# 进程中,有一个执行单位叫线程,
# 进程是资源单位,线程是执行单位...
# 每一个进程在被创建的时候.默认会有一个线程....
# 想让爬虫效率高一些,
# 1.多创建一些线程..让更多的线程帮你工作
# 2.多创建一些进程.让更多个进程帮你干活 本质上,其实还是类似多线程的逻辑......
# 导入包
from threading import Thread # 线程
# 1. 实现多线程的办法
def work():
for i in range(10000):
print("子线程",i)
if __name__ == '__main__':
# main表示主进程里面的主线程
# print("hello world")
# 创建子线程 target表示,该线程需要去执行的任务
t = Thread(target=work)
# 让线程开始执行
t.start() # 让线程开始执行
print("子线程启动完毕")
print("主线程继续执行")
for i in range(10000):
print("主线程",i)
# 2.类继承多线程的方式
# from threading import Thread
#
# # 实现多线程的逻辑
# class MyThread(Thread):
# def run(self): # 任务
# for i in range(1000):
# print("子线程")
#
# if __name__ == '__main__':
# t = MyThread() # 创建线程对象
# t.start() # 启动线程的逻辑都一样
#
# for i in range(1000):
# print("主线程",i)
主与子线程会抢夺打印
二、Python 线程池
c
from concurrent.futures import ThreadPoolExecutor
def work(thread_name):
print("一个任务的开始")
for i in range(100):
print(thread_name,i)
print("一个任务的结束")
if __name__ == '__main__':
with ThreadPoolExecutor(16) as t:
for i in range(10):
# 提交任务. 任务调度/线程开启 不用管
t.submit(work,thread_name=f"子线程{i}")

三、线程池的使用
c
from concurrent.futures import ThreadPoolExecutor
import requests
import time
"""
图片网址:yituyu.com
尝试爬取图片,对比单线和多线程
"""
# 单线程逻辑
# if __name__ == '__main__':
# tm1 = time.time()
# urls = [
# "https://img.yituyu.com/gallery/3979/00_8PxgQG7l-2700x4050.jpg",
# "https://img.yituyu.com/gallery/3979/01_uCGBvl1p-2700x4050.jpg",
# "https://img.yituyu.com/gallery/3979/02_J3py9cRT-2700x4050.jpg",
# "https://img.yituyu.com/gallery/3979/03_udKNR7Xi-2700x4050.jpg",
# "https://img.yituyu.com/gallery/3979/04_pZiaKnbw-4050x2700.jpg",
# "https://img.yituyu.com/gallery/6640/00_3nrH_LZv-2700x4050.jpg",
#
# ]
#
# # 按照之前的逻辑:
# session = requests.Session()
# session.headers = {
"":"" #请求头自行添加
# }
# for url in urls:
# resp = session.get(url)
# name = url.split('/')[-1]
# with open(name,mode="wb") as f:
# f.write(resp.content)
# tm2 = time.time()
# print(tm2-tm1)
# 5.136947393417358
# 4.302821397781372
# 多线程
def download(url):
session = requests.Session()
session.headers = {
"":"" #请求头自行添加
}
resp = session.get(url)
name = url.split('/')[-1]
with open(name,mode="wb") as f:
f.write(resp.content)
if __name__ == '__main__':
tm1 = time.time()
urls = [
"https://img.yituyu.com/gallery/3979/00_8PxgQG7l-2700x4050.jpg",
"https://img.yituyu.com/gallery/3979/01_uCGBvl1p-2700x4050.jpg",
"https://img.yituyu.com/gallery/3979/02_J3py9cRT-2700x4050.jpg",
"https://img.yituyu.com/gallery/3979/03_udKNR7Xi-2700x4050.jpg",
"https://img.yituyu.com/gallery/3979/04_pZiaKnbw-4050x2700.jpg",
"https://img.yituyu.com/gallery/6640/00_3nrH_LZv-2700x4050.jpg",
]
with ThreadPoolExecutor(16) as t:
for url in urls:
t.submit(download,url=url)
tm2 = time.time()
print(tm2-tm1)
# 0.5547342300415039
单线逻辑爬取完需要几秒,多线程0.5秒爬取完。
四、多进程
c
from multiprocessing import Process # 进程
from threading import Thread
# 几乎没人用
from concurrent.futures import ProcessPoolExecutor
def work():
for i in range(100000):
print("子进程",i)
if __name__ == '__main__':
p = Process(target=work)
p.start()
# 进程的开销是比较大的
for i in range(100000):
print("主进程",i)
# 当任务需要隔离的时候。选择使用多进程的思路
# python,天生是有残疾的。由于python有一个GIL锁
# 全局解释器锁。会让python的多线程逻辑无法使用多核CPU
# 我们可以考虑用多进程来解决无法使用多核CPU的问题
# 但是,多进程比较消耗资源,资源开销是比较大的.
# 我们一般是不用的..

主与子进程相互争夺打印
总结
当单纯的只是想要提升效率,多线程
如果多个任务之间,相互隔离... 多进程...