Crawler 15 - corrutina asincrónica

1. El concepto de corrutina y asincrónico.

1.1 Primero importe un fragmento de código

import time
def func():
    print("我爱黎明!")
    time.sleep(3) #睡三秒,让当前线程处于堵塞状态。
    print("我真的爱黎明")
if __name__ == '__main__':
    a = time.time()
    func()
    b = time.time()
    print(b - a)

A juzgar por los resultados de la ejecución, la serie del programa tarda al menos tres segundos en completarse.

我爱黎明!
我真的爱黎明
3.0042407512664795

1.2 Después de más de tres segundos, en realidad no hay trabajo durante tres segundos y el programa entra en estado de suspensión. Durante la suspensión del programa, la CPU no funciona para nuestro programa.

Por ejemplo: en la vida vas a lavarte los pies. Cuando estás en el proceso de remojar tus pies, el técnico no puede masajearte. Puedes hacer otras cosas primero. Después de que hayas terminado de remojar tus pies, vendrán. para masajearte.

1.3 Pensando en el proceso de escritura del programa, ¿hay alguna otra declaración que pueda hacer que el programa entre en estado bloqueado?

# 1. input()语句
# 输入语句 他执行的时候,会让程序停留在终端,等待用户输入,什么时候输入完,再继续往下走

# 2.requests.get(url)
# 当我对url发送请求之后,在网络进行传输,并且url还要准备数据,再传送回来,这个过程我们需要等待服务器那边给我们传输数据,所以也是堵塞状态

#所以总结:
# 一般情况,当程序处于I/O操作的时候(输入,输出),线程会处于堵塞状态

1.4 En el estado bloqueado del programa, en este momento se necesita la operación de rutina.

协程:当程序遇见了I/O操作的时候,可以选择性的切换到其他任务上,充分的利用CPU。
在微观上是一个任务一个任务的进行切换,切换条件一般都是IO操作
在宏观上,我们能看到的其实是多个任务一起在执行
# 简称 多任务异步操作

Según el ejemplo anterior, si el técnico no puede masajearte mientras estás remojando tus pies, puedes pedirle que te frote los hombros, esperar hasta que termine el remojo y luego continuar con el masaje.

Todo lo mencionado anteriormente está bajo la condición de un solo hilo. 

2. Corrutina asincrónica multitarea

2.1 Primero, comprenda simplemente las operaciones de rutina asincrónicas

import asyncio # 导入协程模块

async def func():
    print("我真的爱黎明")
if __name__ == '__main__':
    g = func() # 此时的函数是异步协程函数,
    # print(g) # 此时函数执行得到的是一个协程对象
    asyncio.run(g) # 协程程序运行需要asyncio模块的支持

Cuando solo hay una tarea, no es muy diferente de lo que se escribió antes.

2.2 Introducir corrutina asincrónica multitarea en este momento

Primero introduzca una operación sincrónica.

import time
def func():
    print("你好啊,我叫赛利亚")
    time.sleep(3) # 增加耗时操作
    print("你好啊,我叫赛利亚")
def func1():
    print("你好啊,我叫张东墙")
    time.sleep(2)
    print("你好啊,我叫张东墙")
def func2():
    print("你好啊,我叫王伟")
    time.sleep(4)
    print("你好啊,我叫王伟")

if __name__ == '__main__':
    a=time.time()
    func()
    func1()
    func2()
    b = time.time()
    print(b-a,'s')

En el caso de la sincronización, los programas se operan uno por uno. Al observar los resultados de la ejecución, se puede encontrar que el programa se ejecutó durante más de 9 segundos, de los cuales 9 segundos es el tiempo total de suspensión del programa.

/Users/wangminjie/Desktop/爬虫/venv/bin/python /Users/wangminjie/Desktop/爬虫/线程进程/协程.py
你好啊,我叫赛利亚
你好啊,我叫赛利亚
你好啊,我叫张东墙
你好啊,我叫张东墙
你好啊,我叫王伟
你好啊,我叫王伟
9.008739948272705 s

2.3 Lo siguiente está escrito en forma de rutina asincrónica multitarea

import asyncio
import time
async def func():
    print("你好啊,我叫赛利亚")
    time.sleep(3) # 增加耗时操作
    print("你好啊,我叫赛利亚")
async def func1():
    print("你好啊,我叫张东墙")
    time.sleep(2)
    print("你好啊,我叫张东墙")
async def func2():
    print("你好啊,我叫王伟")
    time.sleep(4)
    print("你好啊,我叫王伟")

if __name__ == '__main__':
    a = time.time()
    p1 = func()
    p2 = func1()
    p3 = func2()
    tasks = [p1, p2, p3]
    # 一次性启动多个任务(协程)
    #多个任务的话,就得交给asyncio.wait来处理
    asyncio.run(asyncio.wait(tasks))
    b = time.time()
    print(b - a, 's')

De los resultados de la ejecución, se puede encontrar que el tiempo de ejecución de la operación asincrónica en este momento es similar al de la operación sincrónica anterior.

2.4 La razón es que time.sleep () es una operación sincrónica. Cuando el programa tiene una operación sincrónica, la operación asincrónica se interrumpirá. En este momento, es necesario reescribir la operación de suspensión del programa en una operación asincrónica asyncio.sleep Y use await se cuelga, cuando se cuelga, el programa pasará al siguiente paso de operación.

import asyncio
import time
async def func():
    print("你好啊,我叫赛利亚")
    # 当程序出现了同步操作的时候,异步就中断了
    #time.sleep(3) # 增加耗时操作
    # await 挂起
    await asyncio.sleep(3) # 异步操作的代码
    print("你好啊,我叫赛利亚")
async def func1():
    print("你好啊,我叫张东墙")
    #time.sleep(2)
    await asyncio.sleep(2)
    print("你好啊,我叫张东墙")
async def func2():
    print("你好啊,我叫王伟")
    #time.sleep(4)
    await asyncio.sleep(4)
    print("你好啊,我叫王伟")

if __name__ == '__main__':
    a = time.time()
    p1 = func()
    p2 = func1()
    p3 = func2()
    tasks = [p1, p2, p3]
    # 一次性启动多个任务(协程)
    #多个任务的话,就得交给asyncio.wait来处理
    asyncio.run(asyncio.wait(tasks))
    b = time.time()
    print(b - a, 's')

De esta manera, se realiza la operación de rutina asincrónica de múltiples tareas y el tiempo total invertido es el período de tiempo más largo en el programa más el tiempo para el cambio de tareas múltiples. 

/Users/wangminjie/Desktop/爬虫/venv/bin/python /Users/wangminjie/Desktop/爬虫/线程进程/协程.py
你好啊,我叫王伟
你好啊,我叫赛利亚
你好啊,我叫张东墙
你好啊,我叫张东墙
你好啊,我叫赛利亚
你好啊,我叫王伟
4.005831956863403 s

2.5 Sin embargo, si escribe rutinas multitarea de esta manera, la función principal funcionará principalmente, por lo que debe cambiar la forma de escribirla y usarla encapsulando una función, y escribirla de esta manera para que sea más perfecta para los rastreadores. .

import asyncio
import time
async def func():
    print("你好啊,我叫赛利亚")
    await asyncio.sleep(3) # 异步操作的代码
    print("你好啊,我叫赛利亚")
async def func1():
    print("你好啊,我叫张东墙")
    await asyncio.sleep(2)
    print("你好啊,我叫张东墙")
async def func2():
    print("你好啊,我叫王伟")
    await asyncio.sleep(4)
    print("你好啊,我叫王伟")
async def main():
    # 第一种写法
    # f1 = func()
    # await f1 # 一般await挂起操作放在协程对象前面
    # ....

    # 第二种写法(推荐)
    tasks = [func(), func1(), func2()]
    await asyncio.wait(tasks)
if __name__ == '__main__':
    a = time.time()
    asyncio.run(main())
    b = time.time()
    print(b - a, 's')

【resultado de la operación】

Y la eficiencia de ejecución sigue siendo la misma que la del programa anterior.

你好啊,我叫张东墙
你好啊,我叫赛利亚
你好啊,我叫王伟
你好啊,我叫张东墙
你好啊,我叫赛利亚
你好啊,我叫王伟
4.006398916244507 s

Pero habrá advertencias al generar, pero esto no afecta la ejecución del programa.

Puede cambiarlo para envolver el objeto de rutina en un objeto tesk antes de usar asyncio.wait. Solo necesita agregar un asyncio.create_task antes del objeto de rutina, lo que equivale a crear una tarea de rutina. 

#tasks = [func(), func1(), func2()]
    
    tasks = [
        asyncio.create_task(func()),
        asyncio.create_task(func1()),
        asyncio.create_task(func2())
    ]
    
    await asyncio.wait(tasks)

Supongo que te gusta

Origin blog.csdn.net/m0_48936146/article/details/124820355
Recomendado
Clasificación