多线程与多进程,+池,以及协程的概念

我们在做爬虫的时候,都会遇到需要爬的数据量特别巨大的,如果按照以往的一 一下载的话,好费的时间很长,效率极低,所以我们可以利用线程加协程的方法大大提高爬虫的效率。

进程是资源单位,每一个进程里至少有一条线程

线程是执行单位,起到的每一个程序都会默认有一个主线程,演示如下:

from threading import Thread #导入多线程模块  

def func ():

    for i in range(1000):

          print('func',i)

if __name__=='__main__':

   t = Thead(target=func)#创建线程并给线程安排任务

         t.start()#多线程状态为可以开始工作状态,具体执行时间由spu决定

  •          for i   in range(1000):
  •                 print('子线程',i)
  • 面向对象写法:

class   MyThread(Thread):

         def run(self):

               for i in range(1000):

                           print('子线程',i)

if __name__ =='__main__':

          t =MyThread()

          t.start()

         for i  in range(1000):

                print ('主线程',i)

 进程的写法跟线程的差不多,只需要导入的进程的模块,然后把要执行的对象加上去就好。

接下来就是多线程池的操作演示:

from concurrent.futures import  ThreadPoolExecutor#多线程池模块
def f(name):
    for i in range(1000):
        print(name,i)

if __name__ == '__main__':
    with ThreadPoolExecutor(50)as t:#创建50个线程池来进行大批量的下载
        for i in range(100):
            t.submit(f,name=f"线程{i}")

    print("123")#等待线程池中的任务完全执行完毕,才继续执行(守护)

协程的概念:

import time
from time import sleep
def func():
    print('我爱你') #让当前的线程处于阻塞状态,cpu是不会工作的
    time.sleep(3)
    print('我真的很爱你')
if __name__ == '__main__':
    func()

ibput() 程序也是处于阻塞状态
requests.get(bilbili)在网络请求返回数据之前,程序也是处于阻塞状态
一般情况下,当程序处于 IO操作的时候,线程都会处于阻塞状态

协程,当程序遇见了IO操作的时候,可以选择性的切换到其他任务上
在微观上是一个任务一个任务的进行切换,切换条件一般就是IO操作
在宏观上,我们能看到的其实是多个任务一起在执行
多任务异步操作
上方所讲的一起,都是在单线程的条件下

协程的创建方式:

import asyncio
import time

t1 =time.time()

async def func1():
    print('你好漂亮')
    time.sleep(3) 
    print('想加你一个微信')
async def func2():
    print('你好漂亮')
    time.sleep(3)
    print('想加你一个微信')
async def func3():
    print('你好漂亮')
    time.sleep(3)
    print('想加你一个微信')

if __name__ == '__main__':
    f1 =func1()
    f2 =func2()
    f3 = func3()
    task ={
        f1,f2,f3
    }
    #一次性启动多个任务(协程)
    asyncio.run(asyncio.wait(task))
    t2 = time.time()
    print( t2-t1)

#但是这个得出的结果是这样的

说明当程序出现了同步操作的时候,异步就中断了,但 这并不是我们想要的结果,要想解决这个问题我们嘚给它加点东西:

import asyncio
import time

t1 =time.time()

async def func1():
    print('你好漂亮')                        
    await asyncio.sleep(3)
    print('想加你一个微信')
async def func2():
    print('你好漂亮')
    await asyncio.sleep(3)
    print('想加你一个微信')
async def func3():
    print('你好漂亮')
    await asyncio.sleep(3)
    print('想加你一个微信')

if __name__ == '__main__':
    f1 =func1()
    f2 =func2()
    f3 = func3()
    task ={
        f1,f2,f3
    }
    #一次性启动多个任务(协程)
    asyncio.run(asyncio.wait(task))
    t2 = time.time()
    print( t2-t1)

 注意:await是挂起的意思,一般这个操作都会在协程对象前面

用异步的操作代码,来处理这个问题得出的结果是:

 不过这样太麻烦了,有个官方推荐的方法:

async def main():
      task =[
          asyncio.create_task(func1()),#转换成task对象
          asyncio.create_task(func2()),
          asyncio.create_task(func3())
      ]
      await asyncio.wait(task)

if __name__ == '__main__':
    asyncio.run(main())

 直接写一个异步总函数,需要的时候直接调用就好。省事,方便。也可以完美的套在我们的爬虫代码上

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值