VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > Python基础教程 >
  • python asyncio aiohttp 异步下载 完整例子

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/dashoumeixi/article/details/81085141
asyncio 基础:python asyncio 协程
 
之前完整的说明了并发下载例子: 并发下载
 
使用了aiohttp,
 
注意, 下面写文件没有使用异步写入.一般情况下可以配合ThreadPoolExecutor来结合写入文件 : 关于aiohttp下载大文件的方式
 
import os,sys,time,asyncio,aiohttp
import tqdm
FLAGS = ('CN IN US ID BR PK NG BD RU JP ' 
         'MX PH VN ET EG DE IR TR CD FR').split()
BASE_URL = 'http://flupy.org/data/flags'        #下载url
DEST_DIR = 'downloads/'                           #保存目录
#获取链接,下载文件
async def fetch(session:aiohttp.ClientSession,url:str,path:str,flag:str):
    print(flag, ' 开始下载')
    async with session.get(url) as resp:
        with open(path,'wb') as fd:
            while 1:
                chunk = await resp.content.read(1024)    #每次获取1024字节
                if not chunk:
                    break
                fd.write(chunk)
    return flag
 
async def begin_download(sem,session:aiohttp.ClientSession,url:str,path:str,flag:str):
    #控制协程并发数量
    with (await sem):
        return await fetch(session,url,path,flag)
 
async def download(sem:asyncio.Semaphore):
    tasks = []
    async with aiohttp.ClientSession() as session:
        for flag in FLAGS:
            #创建路径以及url
            path = os.path.join(DEST_DIR, flag.lower() + '.gif')
            url = '{}/{cc}/{cc}.gif'.format(BASE_URL, cc=flag.lower())
            #构造一个协程列表
            tasks.append(asyncio.ensure_future(begin_download(sem,session, url, path, flag)))
        #等待返回结果
        tasks_iter = asyncio.as_completed(tasks)
        #创建一个进度条
        fk_task_iter = tqdm.tqdm(tasks_iter,total=len(FLAGS))
        for coroutine in fk_task_iter:
            #获取结果
            res = await coroutine
            print(res, '下载完成')
 
#创建目录
os.makedirs(DEST_DIR,exist_ok=True)
#获取事件循环
lp = asyncio.get_event_loop()
start = time.time()
#创建一个信号量以防止DDos
sem = asyncio.Semaphore(4)
lp.run_until_complete(download(sem))
end = time.time()
lp.close()
print('耗时:',end-start)
 
 
在写文件那块代码可以使用 run_in_executor 这个函数执行,事件循环中包含一个默认的线程池(ThreadPoolExecutor).
 
run_in_executor(executor, func, *args) 原型 . executor == None, 使用默认的. 可以自己创建一个;
 
具体代码:
 
#线程运行的函数
def save_file(fd:io.BufferedWriter,chunk):
    fd.write(chunk)
#获取链接,下载文件
async def fetch(session:aiohttp.ClientSession,url:str,path:str,flag:str):
    print(flag, ' 开始下载')
    async with session.get(url) as resp:
        with open(path,'wb') as fd:
            while 1:
                chunk = await resp.content.read(8192)
                if not chunk:
                    break
                lp = asyncio.get_event_loop()
                lp.run_in_executor(None,save_file,fd,chunk)
                # fd.write(chunk)
    return flag
 
 
 
————————————————
版权声明:本文为CSDN博主「dashoumeixi」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/dashoumeixi/article/details/81085141

相关教程