46.python之异步

异步

  • 一般代码是从上而下执行的,比如有3个打印语句,正常执行是从第一个到最后一个按照顺序打印出来,也就是后面的打印语句会等待前面的打印语句执行完后在执行,这个是同步执行,同步意味着有序执行;
  • 而异步就是,后面的打印语句不会等待前面的执行完后再执行,也就是说异步不会阻塞其他任务执行,异步意味着无序执行

异步与多线程多进程:

  • 异步是轻量级的线程,可以叫做协程
  • 多进程和多线程无法获取函数的返回值,但是异步可以获取函数的返回值,进程池和线程池可以说是有异步的效果,它们可以获取函数的返回值
  • 主进程是异步才可以使用
  • 异步更适合需要返回值的操作,比如文件读写使用
  • 多线程和多进程更适合不需要返回值的操作

async与await关键字

  • Python3.4后才有的
  • async 定义异步
  • await 执行异步

用法:

# 定义异步函数
async def test(a):
    return a
    
# 执行异步
async def t2():
    res = await test(1)

asyncio模块:

  • 调用异步模块执行
  • 内置了对异步IO的支持,用于处理异步IO
  • 提供了使用协程构建并发应用的工具
  • asyncio提供的框架以事件循环(event loop)为中心,程序开启一个无限的循环,程序会把一些函数注册到事件循环上。当满足事件发生的时候,调用相应的协程函数

asyncio调用async函数
在这里插入图片描述

用法:

async def main():
    result = await asyncio.gather(a(),b()) 
    print(result)
    
if __name__ == '__main__':
    asyncio.run(main())

例1:非异步

import time
import os

def test1():
    for i in range(3):
        print(f'test1,i={i},进程号:{os.getpid()}')
        time.sleep(1)

def test2():
    for j in range(3):
        print(f'test2,j={j},进程号:{os.getpid()}')
        time.sleep(1)

if __name__ == '__main__':
    # 开始时间
    start_time = time.time()
    test1()
    test2()

    print(f'时间间隔:{time.time()-start_time},进程号:{os.getpid()}')

结果:

  • 按照顺序执行,间隔时间是6s,且所有的任务都是一个进程执行
    在这里插入图片描述

例2:异步

import time
import os
import asyncio
import threading

# 定义异步函数
async def test1():
    for i in range(3):
        print(f'test1,i={i},进程号:{os.getpid()},线程名称是:{threading.current_thread().name}')
        # 注意这里的等待时间也要修改成异步
        # time.sleep是cpu阻塞,asyncio.sleep是当前业务阻塞
        await asyncio.sleep(1)
    return "test1"

async def test2():
    for j in range(3):
        print(f'test2,j={j},进程号:{os.getpid()},线程名称是:{threading.current_thread().name}')
        # 注意这里的等待时间也要修改
        await asyncio.sleep(1)
    return "test2"

# 定义主异步函数
async def main():
    # 批量执行异步函数
    result = await asyncio.gather(test1(), test2())
    # 打印函数的返回值
    print(f'函数返回值:{result},线程名称是:{threading.current_thread().name}')
    return '我是主函数'

if __name__ == '__main__':
    # 开始时间
    start_time = time.time()
    # 执行主异步函数
    ar = asyncio.run(main())
    print(f'{ar},线程名称是:{threading.current_thread().name}')

    print(f'时间间隔:{time.time()-start_time},进程号:{os.getpid()},线程名称是:{threading.current_thread().name}')

结果:

  • 2个函数异步执行,时间间隔是3s,进程号相同,有点类似多线程,不过都是一个线程执行的
  • 它使用一种单线程单进程的的方式实现并发,应用的各个部分彼此合作, 可以显示的切换任务,一般会在程序阻塞I/O操作的时候发生上下文切换如等待读写文件,或者请求网络。
  • 同时asyncio也支持调度代码在将来的某个特定事件运行,从而支持一个协程等待另一个协程完成,以处理系统信号和识别其他一些事件。
    在这里插入图片描述

gevent模块:创建协程对象

环境准备

安装 pip install gevent

gevent模块方法
在这里插入图片描述

Gevent协程对象的方法:
在这里插入图片描述

例:

import time
import os
import gevent
import threading

def test1(count):
    for i in range(count):
        print(f'test1,i={i},进程号:{os.getpid()},线程名称是:{threading.current_thread().name}')
        # 注意这里的时间也要修改成异步
        gevent.sleep(1)
    return "test1"

def test2():
    for j in range(3):
        print(f'test2,j={j},进程号:{os.getpid()},线程名称是:{threading.current_thread().name}')
        # 注意这里的时间也要修改
        gevent.sleep(1)
    return "test2"

if __name__ == '__main__':
    # 开始时间
    start_time = time.time()

    # 创建协程对象
    g1 = gevent.spawn(test1, 3)
    g2 = gevent.spawn(test2)

    # 批量处理协程对象
    g_list = [g1, g2]
    result = gevent.joinall(g_list)

    # 打印异步函数的返回值
    # 方式1:
    print(f'test1函数返回值:{g1.get()}')
    # 方式2:
    print(result[0].value, result[1].value)

    print(f'时间间隔:{time.time()-start_time},进程号:{os.getpid()},线程名称是:{threading.current_thread().name}')

结果:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python爬虫异步是指使用并发的方式进行网页数据的获取和处理,以提高效率和性能。在异步爬虫,可以使用多种方法实现异步操作,如使用aiohttp和asyncio库进行异步HTTP请求,使用协程来处理异步任务,以及使用线程池和进程池来实现异步执行等。 一种常见的异步爬虫实现方式是使用aiohttp和asyncio库。通过创建一个信号量对象,可以控制并发量的大小,使用async with语句将信号量作为上下文对象,从而在爬取方法控制并发量。另外,在main方法使用asyncio.gather方法来同时执行多个爬取任务,以提高效率。 另一种实现异步爬虫的方式是使用asyncio库的wait方法来执行多个请求任务。首先,将需要执行的任务封装成协程对象,并放入一个任务列表。然后,使用asyncio.wait方法来执行任务列表的任务,并通过循环获取每个任务的结果。 除了使用aiohttp和asyncio库,还可以使用其他库来实现异步爬虫。例如,使用aiohttp库结合时间模块来控制请求的延迟时间,从而模拟异步请求的效果。在get方法使用await关键字挂起请求,并在得到响应后再继续执行。 此外,还可以使用线程池或进程池来实现异步爬虫。通过使用multiprocessing.dummy库的Pool类,可以创建一个线程池,并使用map方法将任务分配到多个线程并发执行。这样可以降低系统对线程或进程的创建和销毁频率,提高系统的性能和效率。 综上所述,Python爬虫异步是通过使用异步操作的方式来提高爬取效率和性能的一种方法。可以使用aiohttp和asyncio库、线程池或进程池等不同的工具和技术来实现异步爬虫。这些方法都能够提供更高并发量和更快的响应速度,从而提升爬虫的效率。<span class="em">1</span><span class="em">2</span><span class="em">3</span><span class="em">4</span>

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值