协程的使用

Posted py-peng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了协程的使用相关的知识,希望对你有一定的参考价值。

asyncio

快速使用

import asyncio

async def request(url):
    print("request正在执行 %s"%url)
    print("request执行完成 %s"%url)

# 创建实践循环
event_loop = asyncio.get_event_loop()
# 启动
event_loop.run_until_complete(request("www.baidu.com"))

 

task与future

本质没差别,只是调用的方法不同。

task基于事件循环来创建

future基于asyncio来创建

import asyncio

async def request(url):
    print("request正在执行 %s"%url)
    print("request执行完成 %s"%url)

# 创建实践循环
event_loop = asyncio.get_event_loop()
# 创建future与task对象
future = asyncio.ensure_future(request("www.baidu.com"))
task = event_loop.create_task(request("www.google.com"))
# 启动
event_loop.run_until_complete(future)
event_loop.run_until_complete(task)

 

回调函数

import asyncio

async def request(url):
    print("request正在执行 %s"%url)
    return "request执行完成 %s"%url

def callback_func(task):
    print(task.result()) # result 获取返回值

# 创建实践循环
event_loop = asyncio.get_event_loop()
# 创建task对象
task = event_loop.create_task(request("www.badidu.com"))
# 绑定回调函数
task.add_done_callback(callback_func)
# 启动
event_loop.run_until_complete(task)

 

多任务操作

上面的实例,都是单任务操作。

import asyncio
import time

async def request(url):
    print("request正在执行 %s"%url)
    await asyncio.sleep(2)
    return "request执行完成 %s"%url

def callback_func(task):
    print(task.result()) # result 获取返回值

event_loop = asyncio.get_event_loop() # 创建事件循环
urls = ["www.baidu.com","www.douban.com","www.python.com"]
tasks = []
for url in urls:
    task = event_loop.create_task(request(url)) # 创建task
    task.add_done_callback(callback_func) # 绑定回调函数
    tasks.append(task)
start_time = time.time()
event_loop.run_until_complete(asyncio.wait(tasks)) # 启动
end_time = time.time() - start_time
print(end_time)

 

为什么没用time.time(),而是await asyncio.sleep()

如果出现同步模块相关的代码,那么就无法实现异步。

await asyncio.sleep(),代码中await是什么?

当asyncio遇到堵塞操作,需手动挂起,而挂起就需要await来实现。

 

使用协程爬去数据

asyncio不能单独完成网络的协程,需要与aiohttp配合才行。

https://www.cnblogs.com/py-peng/p/12256019.html

import asyncio
import aiohttp
from fake_useragent import UserAgent

async def get_source(url):
    ua = UserAgent().random # 获取随机ua
    headers = {"User-Agent":ua}
    async with aiohttp.ClientSession() as session: # 创建session
        async with session.get(url,headers=headers,verify_ssl=False) as response: # 发送请求
            text = await response.read() # 读取二进制数据,text()是文本,前面需要加await
            print("Text Count: %s"%len(text))

urls = ["http://baidu.com","http://douban.com","http://qq.com/"]
tasks = []
event_loop = asyncio.get_event_loop()
for url in urls:
    task = event_loop.create_task(get_source(url)) # 创建task
    tasks.append(task)
event_loop.run_until_complete(asyncio.wait(tasks)) # 启动

 

gevent

快速使用

import gevent

def get_source(url):
    print("正在请求 %s"%url)
    gevent.sleep(2)
    return "执行完成 %s"%url

g = gevent.spawn(get_source,"www.baidu.com") # 生成对象
result = g.get() # 获取函数返回值
print(result)

 

多任务操作

import gevent

def get_source(url):
    print("正在请求 %s"%url)
    gevent.sleep(2)
    return "执行完成 %s"%url

def get_event(url,spawn_func):
    return gevent.spawn(spawn_func, url)

urls = ["http://www.baidu.com","http://www.douban.com","http://www.python.org"]
response = gevent.joinall([get_event(url,get_source) for url in urls]) # 生产事件对象
for rep in response:
    print(rep.get()) # 获取结果

 

使用协程爬去数据

必须导入gevent文件夹下的monkey,还需要使用monkey这个函数。

from gevent import monkey # 导入monkey
monkey.patch_all() # 使用该函数

import gevent
import requests

def get_source(url):
     response = requests.get(url)
     return "Source: %s --- Status: %s"%(url, response.status_code)

def get_event(url,spawn_func):
    return gevent.spawn(spawn_func, url)

urls = ["http://www.baidu.com","http://www.douban.com","http://www.python.org"]
response = gevent.joinall([get_event(url,get_source) for url in urls]) # 生产协程对象
for rep in response:
    print(rep.get())

 

以上是关于协程的使用的主要内容,如果未能解决你的问题,请参考以下文章

Kotlin协程的Jacoco代码覆盖率不正确

协程的概念

关于协程:nodejs和golang协程的不同

如何在主函数中恢复协程的执行?

使用协程的 Kotlin/Native 多线程

Kotlin协程源码分析-协程的启动