| 解释 | |
|---|---|
| 并行 | 真的多任务 |
| 并发 | 假的多任务,只不过运行速度非常块,感觉上像是多个一起运行 |
注释1 : 利用单线程的空闲时间即为异步.
asyncio模块最大的特点是只存在一个线程,在这个线程中可以实现个任务"一起执行".
| 格式 | |
|---|---|
| 定义异步函数 | async def test(): |
| 调用异步函数 | asyncio.run(test()) |
| 创建协程对象,在这个协程对象中创建其他的协程对象来实现真正的任务代码 | async def main(): await asyncio.gather(test1(),test2()) |
| 调用多个异步函数 | await asyncio.gather(test1(),test2()) |
注释1 : 在异步爬虫中不要使用同步的模块
import time
def Hello():
time.sleep(1)
def run():
for i in range(5):
Hello()
print(f"执行第{i+1}次所用时间:{time.time()}")
if __name__ == '__main__':
run()
import time
import asyncio
async def Hello():
await asyncio.sleep(1)
print(f"执行所用时间:{time.time()}")
# 定义异步函数(一个异步函数可以认为就是一个协程)
async def run(): # 加async变为异步函数
tasks = list()
for i in range(5):
tasks.append(Hello())
await asyncio.wait(tasks)
if __name__ == '__main__':
asyncio.run(run()) # 调用异步函数
import asyncio
def test1():
"""
这是一个同步函数
"""
print("test1")
return 1
async def test2():
"""
这是一个异步函数
"""
print("test2")
return 2
async def test3():
"""
这是一个异步函数
"""
print("test3")
return 3
async def test4():
"""
这是一个异步函数
"""
print("test4")
return 4
# 1.调用同步函数
print(test1())
print("-------------------------")
# 2.调用异步函数
print(asyncio.run(test4()))
print("-------------------------")
if __name__ == '__main__':
# 创建一个事件循环
loop = asyncio.get_event_loop()
# 创建协程(此时test4这个协程中的任务代码并没有真正的开始执行)
t3 = test3()
# 进入事件循环
print(loop.run_until_complete(t3))
# 关闭事件循环
loop.close()
"""
print(test4())不是在调用函数,而是在创建对象
"""
import asyncio
async def test0():
"""
这是一个异步函数
"""
print("test0")
return 0
if __name__ == '__main__':
# 创建一个事件循环
loop = asyncio.get_event_loop()
# 创建协程(此时test4这个协程中的任务代码并没有真正的开始执行)
t0 = test0()
# 进入事件循环
print(loop.run_until_complete(t0))
# 关闭事件循环
loop.close()
import asyncio
async def test1():
for i in range(3):
print("协程A_1.0")
await asyncio.sleep(0)
print("协程A_2.0")
async def test2():
for i in range(5):
print("协程B_1.0")
"""
因为在test1协程中执行到了asyncio.sleep(),无论sleep时间是多少,此
时event loop检查到进行延时,此时event loop就可以将代码的调度权限给
test2协程对象,此时test2开始执行
"""
await asyncio.sleep(0) # 会导致event loop开始找下一个可以运行的协程对象
print("协程B_2.0")
async def main():
# 2.创建了其他的协程对象,在这些协程对象中实现真正的任务代码
await asyncio.gather(test1(), test2())
if __name__ == '__main__':
# 1.创建一个coroutine对象(协程)
asyncio.run(main())
"""
help1: asyncio 用 task(任务) 来实现异步.
"""
import asyncio
import time
async def test1():
print(f"协程A_StartTime: {time.time()}")
for i in range(10):
print(f"→执行第{i+1}次协程A")
await asyncio.sleep(1)
print(f"协程A_StopTime: {time.time()}")
async def test2():
print(f"协程B_StartTime: {time.time()}")
for i in range(10):
print(f"→执行第{i+1}次协程B")
await asyncio.sleep(1)
print(f"协程B_StopTime: {time.time()}")
async def main():
task1 = asyncio.create_task(test1()) # create_task()对协程对象进行封装,使其具备更高级的功能
task2 = asyncio.create_task(test2())
print("------------------------------")
print(f"task1 is over? 状态为:{task1.done()}") # done()返回当前状态(True或False)
print(f"task2 is over? 状态为:{task2.done()}")
# 多个task任务
tasks = [task1, task2]
await asyncio.wait(tasks) # wait()是等待列表中的内容执行完毕
print("------------------------------")
print(f"task1 is over? 状态为:{task1.done()}")
print(f"task2 is over? 状态为:{task2.done()}")
if __name__ == '__main__':
start_time = time.time()
asyncio.run(main())
stop_time = time.time()
print("------------------------------")
print(f"总耗时:{stop_time-start_time}")
import asyncio
async def test():
print("------------------------------")
print("→执行test")
return 100
async def main():
task = asyncio.create_task(test())
# 单个task任务
await task
print("------------------------------")
print(f"task is over? 状态为:{task.done()}")
print(f"test的返回值为: {task.result()}")
if __name__ == '__main__':
asyncio.run(main())
import asyncio
def callback_after_done(task_obj):
# 该函数在test任务完成后自动调用,会自动将完成后的task对象当作参数传递
print("------------------------------")
print(f"→callback_after_done_1: {task_obj}")
print(f"→callback_after_done_2: {task_obj.done()}")
print(f"→callback_after_done_3: {task_obj.result()}")
async def test():
print("→执行test")
return 100
async def main():
task = asyncio.create_task(test())
task.add_done_callback(callback_after_done) # 注意该参数是函数名,不是函数名()
# 单个task任务
await task
print("------------------------------")
print(f"task is over? 状态为:{task.done()}")
print(f"test的返回值为: {task.result()}")
if __name__ == '__main__':
asyncio.run(main())
import asyncio
import functools
def callback_after_done(task_obj, num1, num2):
# 该函数在test任务完成后自动调用,会自动将完成后的task对象当作参数传递
print("------------------------------")
print(f"→callback_after_done_1: {task_obj}")
print(f"→callback_after_done_2: {task_obj.done()}")
print(f"→callback_after_done_3: {num1},{num2}")
async def test():
print("→执行test")
return 100
async def main():
task = asyncio.create_task(test())
# functools.partial()给回调函数传递参数
task.add_done_callback(functools.partial(callback_after_done, num1=100, num2=200))
# 单个task任务
await task
print("------------------------------")
print(f"task is over? 状态为:{task.done()}")
print(f"test的返回值为: {task.result()}")
if __name__ == '__main__':
asyncio.run(main())
"""
help1: request模块是同步的,而aiohttp相当于是异步版的request模块.
"""
import asyncio
import aiohttp
tasks = []
url = "https://www.baidu.com"
async def get_Baidu(u):
async with aiohttp.ClientSession() as session: # async的意思是耗费时间太长就切换任务,with表示打开,as是取的别名
async with session.get(url) as r:
resp_text = await r.text() # await等待其后面代码执行完毕
print(resp_text)
if __name__ == '__main__':
# loop = asyncio.get_event_loop() # 创建一个事件循环
# loop.run_until_complete(get_Baidu(u=url)) # 进入事件循环
asyncio.run(get_Baidu(url))
import asyncio
import aiohttp
def dowload_completed_callback(task_obj):
print(f"下载的内容为:{task_obj.result()}")
async def baidu_spider():
print("==========百度蜘蛛==========")
url = "https://www.baidu.com"
async with aiohttp.ClientSession() as session:
async with session.get(url) as r:
return await r.text()
async def sogou_spider():
print("==========搜狗蜘蛛==========")
url = "https://www.sogou.com"
async with aiohttp.ClientSession() as session:
async with session.get(url) as r:
return await r.text()
async def jingdong_spider():
print("==========京东蜘蛛==========")
url = "https://www.jd.com"
async with aiohttp.ClientSession() as session:
async with session.get(url) as r:
return await r.text()
async def main():
# 创建多个task,且添加回调函数
task_baidu = asyncio.create_task(baidu_spider())
task_baidu.add_done_callback(dowload_completed_callback)
task_sogou = asyncio.create_task(sogou_spider())
task_sogou.add_done_callback(dowload_completed_callback)
task_jingdong = asyncio.create_task(jingdong_spider())
task_jingdong.add_done_callback(dowload_completed_callback)
# 等待下载
tasks = [task_baidu, task_sogou, task_jingdong]
await asyncio.wait(tasks)
if __name__ == '__main__':
asyncio.run(main())