三:asyncio(>=python3.4)
Python3.4以上的版本还可以使用asyncio来实现协程,具体代码如下:
ruby
复制代码
#!/usr/bin/python3 # -*- coding: utf-8 -*- # @Time : 2022/3/17 19:38 # @Author : camellia # @Email : 805795955@qq.com # @File : coroutine.py # @Software: PyCharm # 测试协程程序 import asyncio @asyncio.coroutine def fun1(): print(1) yield from asyncio.sleep(1) print(2) @asyncio.coroutine def fun2(): print(3) yield from asyncio.sleep(1) print(4) # 任务列表 tasks = [ asyncio.ensure_future(fun1()), asyncio.ensure_future(fun2()) ] # 时间循环 loop = asyncio.get_event_loop() # 执行 loop.run_until_complete(asyncio.wait(tasks))
执行上边的代码,输出:
复制代码
1 3 2 4
Asyncio这个就比较厉害了,他是自动切换执行方法的。上边我们看到的yield与greenled都是我们人为控制的。这就很高级。
四:async await关键字(>=python3.5)(推荐使用)
Python3.5以上才可以使用async与await,这两个关键字其实就是替代我们上边使用到的yield关键字,因此我们只需要将上方的程序做一下小修改即可:
python
复制代码
#!/usr/bin/python3 # -*- coding: utf-8 -*- # @Time : 2022/3/17 19:38 # @Author : camellia # @Email : 805795955@qq.com # @File : coroutine.py # @Software: PyCharm # 测试协程程序 import asyncio async def fun1(): print(1) await asyncio.sleep(1) print(2) async def fun2(): print(3) await asyncio.sleep(1) print(4) # 任务列表 tasks = [ asyncio.ensure_future(fun1()), asyncio.ensure_future(fun2()) ] # 时间循环 loop = asyncio.get_event_loop() # 执行 loop.run_until_complete(asyncio.wait(tasks))
以上大概就是python中四种实现协程的方式。
五:协程的意义
在线程中如果遇到IO等待时间,线程不会去傻等,利用空闲的时候再去做点其他的事。
干说没有代码实现来的醒目。下边我们使用一个例子来展示一下:
下载三张图片,第一种实现方式,使用正常的同步下载。
第二种实现方式使用协程来下载。对比下载时间。
同步爬取:
python
复制代码
#!/usr/bin/python3 # -*- coding: utf-8 -*- # @Time : 2022/3/17 19:38 # @Author : camellia # @Email : 805795955@qq.com # @File : coroutine.py # @Software: PyCharm # 测试协程程序 import time import requests import random import string import asyncio start =time.clock() def getImage(): """ :name 爬取网络图片 :param url: 图片url :param num: 图片名称 :return: 无返回值 """ lis = [ "https://resource.guanchao.site/uploads/sowing/welcome-image3.jpg", "https://resource.guanchao.site/uploads/sowing/welcome-image7.jpg", "https://resource.guanchao.site/uploads/sowing/welcome-image5.jpg" ] for item in lis: # 1:指定url # url = "https://resource.guanchao.site/uploads/sowing/welcome-image3.jpg" # 2:模拟网络请求链接 responce = requests.get(url=item) print('爬取:'+item) # 3:获取响应数据,content获取二进制数据 content = responce.content filename = './img/' + ''.join(random.sample(string.ascii_letters + string.digits, 8)) + '.jpg' # 4:持久化存储 with open(filename, 'wb') as fe: fe.write(content) print('爬取完成') getImage() end = time.clock() print('Running time: %s Seconds'%(end-start))
输出:
ruby
复制代码
爬取:https://resource.guanchao.site/uploads/sowing/welcome-image3.jpg 爬取完成 爬取:https://resource.guanchao.site/uploads/sowing/welcome-image7.jpg 爬取完成 爬取:https://resource.guanchao.site/uploads/sowing/welcome-image5.jpg 爬取完成 Running time: 2.4804463 Seconds
协程爬取:
协程爬取使用aiohttp模块
python
复制代码
#!/usr/bin/python3 # -*- coding: utf-8 -*- # @Time : 2022/3/17 19:38 # @Author : camellia # @Email : 805795955@qq.com # @File : coroutine.py # @Software: PyCharm # 测试协程程序 import time import requests import random import string import asyncio import aiohttp start =time.clock() async def fetch(session,url): print('发送请求:'+url) async with session.get(url,verify_ssl=False) as response: content = await response.content.read() filename = './img/' + ''.join(random.sample(string.ascii_letters + string.digits, 8)) + '.jpg' # 4:持久化存储 with open(filename, 'wb') as fe: fe.write(content) print('爬取完成') async def mains(): async with aiohttp.ClientSession() as session: lis = [ "https://resource.guanchao.site/uploads/sowing/welcome-image3.jpg", "https://resource.guanchao.site/uploads/sowing/welcome-image7.jpg", "https://resource.guanchao.site/uploads/sowing/welcome-image5.jpg" ] tasks = [asyncio.create_task(fetch(session,url)) for url in lis] await asyncio.wait(tasks) # asyncio.run(mains()) loop = asyncio.get_event_loop() loop.run_until_complete(mains())
执行代码:
ruby
复制代码
发送请求:https://resource.guanchao.site/uploads/sowing/welcome-image3.jpg 发送请求:https://resource.guanchao.site/uploads/sowing/welcome-image7.jpg 发送请求:https://resource.guanchao.site/uploads/sowing/welcome-image5.jpg 爬取完成 爬取完成 爬取完成 Running time: 1.8801726 Seconds
我们可以根据 输出的文字顺序看到代码是如何执行的。并且执行速度更快。
有好的建议,请在下方输入你的评论。