摘要:異步下載國旗圖片和國家名數(shù)據(jù)用來捕獲異常保存圖片文件負責(zé)下載的主函數(shù),由傳遞國家名是數(shù)據(jù)。異步獲取圖片異步獲取國家名中的子句在沒有異常時會運行這里獲取循環(huán)是為了在保存圖片時不阻塞函數(shù)內(nèi)部維護了一個對象注。
異步下載國旗圖片和國家名數(shù)據(jù)
import aiohttp import asyncio import os import time import sys POP20_CC = ("CN IN US ID BR PK NG BD RU JP MX PH VN ET EG DE IR CD FR").split() BASE_URL = "http://flupy.org/data/flags" DEST_DIR = "downloads/" class FetchError(Exception): #用來捕獲異常 def __init__(self, country_code): self.country_code = country_code def save_flag(img, filename): #保存圖片文件 path = os.path.join(DEST_DIR, filename) with open(path, "wb") as fp: fp.write(img) async def http_get(session, url): #負責(zé)下載的主函數(shù),session由download_many傳遞 async with session.get(url) as resp: if resp.status == 200: ctype = resp.headers.get("Content-type", "").lower() if "json" in ctype or url.endswith(".json"): #國家名是json數(shù)據(jù)。如果內(nèi)容類型是json data = await resp.json() #那么就用json()方法獲取內(nèi)容 else: data = await resp.read() #否則直接獲取元數(shù)據(jù) return data elif resp.status == 404: #捕獲異常 raise web.HTTPNotFound() else: raise aiohttp.errors.HttpProcessingError(code=res.sstatus, message=res.reason, headers=res.headers) async def get_flag(session, cc): #獲取圖片 url = "{}/{cc}/{cc}.gif".format(BASE_URL, cc=cc.lower()) image = await http_get(session, url) #這里是Io請求需要異步操作 return image async def get_country(session, cc): #獲取國家名 url = "{}/{cc}/metadata.json".format(BASE_URL, cc=cc.lower()) metadata = await http_get(session, url) #這里是Io請求需要異步操作 return metadata["country"] def show(text): print(text + "[OK] ", end="") sys.stdout.flush() #挨個輸出國家名,沒有這個刷新緩沖區(qū)方法就會最后一下子輸出所有國家名。 async def download_one(session, cc): try: image = await get_flag(session, cc) #異步獲取圖片 country = await get_country(session, cc) #異步獲取國家名 except web.HTTPNotFound: msg = "not found" except Exception as exc: raise FetchError(cc) from exc else: #try中的else子句在沒有except異常時會運行 country = country.replace(" ", "_") filename = "{}-{}.gif".format(cc, country) loop = asyncio.get_event_loop() #這里獲取循環(huán)是為了在保存圖片時不阻塞 loop.run_in_executor(None, save_flag, image, filename) #run_in_excutor函數(shù)內(nèi)部維護了一個TheardPollExecutor對象[注1]。第一個參數(shù)默認為concurrent.futures.Executor實例。 show(cc) return cc async def download_many(cc_list): async with aiohttp.ClientSession() as session: #獲取ClientSession對象 res = await asyncio.gather(*[asyncio.ensure_future(download_one(session, cc)) for cc in sorted(cc_list)]) #gather函數(shù)如果參數(shù)為協(xié)程對象它會自動排定為一個task,這里我們直接用的ensure_future方法生成了task對象。然后并發(fā)的運行他們,返回一個結(jié)果聚合值列表。 return len(res) def main(): t0 = time.time() loop = asyncio.get_event_loop() count = loop.run_until_complete(download_many(POP20_CC)) loop.close() elapsed = time.time() - t0 msg = " {} flags download in {:.2f}s" print(msg.format(count, elapsed)) if __name__ == "__main__": main() #def a(*x): #print(x) #a([1,2]) --> ([1,2],) #a(*[1,2]) --> (1,2) #*號可以將列表或元組里的元素解包,每個元素作為多帶帶的參數(shù)傳入
其實,異步庫依賴于低層線程(直至內(nèi)核級線程),但是這些庫的用戶無需創(chuàng)建線程,也無需知道用到了基礎(chǔ)設(shè)施中的低層線程。在應(yīng)用中,我們只需確保沒有阻塞的代碼,事件循環(huán)會在背后處理并發(fā)。異步系統(tǒng)能避免用戶線程級的開銷,這是它能比多線程系統(tǒng)管理更多并發(fā)連接的原因。
【注1】The loop.run_in_executor() method can be used with a concurrent.futures.ThreadPoolExecutor to execute blocking code in a different OS thread without blocking the OS thread that the event loop runs in.
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/43818.html
摘要:介紹本篇博客將繼續(xù)上一篇博客爬蟲之使用的模塊爬取各國國旗的內(nèi)容,將用來實現(xiàn)這個爬蟲,下載全世界國家的國旗圖片。 介紹 ??本篇博客將繼續(xù)上一篇博客:Python爬蟲之使用Fiddler+Postman+Python的requests模塊爬取各國國旗 的內(nèi)容,將用Java來實現(xiàn)這個爬蟲,下載全世界國家的國旗圖片。項目不再過多介紹,具體可以參考上一篇博客。??我們將全世界國家的名稱放在一個...
摘要:流程作為上述過程的一個演示,我們使用的網(wǎng)址為頁面如下在表單中輸入德國,跳轉(zhuǎn)后的頁面如下我們可以發(fā)現(xiàn),在搜索的結(jié)果中,會出現(xiàn)德國這個搜索結(jié)果。點擊該搜索結(jié)果,跳轉(zhuǎn)后的頁面如下在這個頁面中有我們需要的德國的國旗。 介紹 ??本篇博客將會介紹一個Python爬蟲,用來爬取各個國家的國旗,主要的目標是為了展示如何在Python的requests模塊中使用POST方法來爬取網(wǎng)頁內(nèi)容。??為了知道...
摘要:標準庫中所有阻塞型函數(shù)都會釋放,允許其他線程運行。如果調(diào)用引發(fā)異常,那么當從迭代器檢索其值時,將引發(fā)異常??偨Y(jié)自版就支持線程了,只不過是使用線程的最新方式。類封裝了模塊的組件,使使用線程變得更加方便。下一篇筆記應(yīng)該是使用處理并發(fā)。 作為Python程序員,平時很少使用并發(fā)編程,偶爾使用也只需要派生出一批獨立的線程,然后放到隊列中,批量執(zhí)行。所以,不夸張的說,雖然我知道線程、進程、并行、...
摘要:是之后引入的標準庫的,這個包使用事件循環(huán)驅(qū)動的協(xié)程實現(xiàn)并發(fā)。沒有能從外部終止線程,因為線程隨時可能被中斷。上一篇并發(fā)使用處理并發(fā)我們介紹過的,在中,只是調(diào)度執(zhí)行某物的結(jié)果。 asyncio asyncio 是Python3.4 之后引入的標準庫的,這個包使用事件循環(huán)驅(qū)動的協(xié)程實現(xiàn)并發(fā)。asyncio 包在引入標準庫之前代號 Tulip(郁金香),所以在網(wǎng)上搜索資料時,會經(jīng)??吹竭@種花的...
摘要:本文重點掌握異步編程的相關(guān)概念了解期物的概念意義和使用方法了解中的阻塞型函數(shù)釋放的特點。一異步編程相關(guān)概念阻塞程序未得到所需計算資源時被掛起的狀態(tài)。 導(dǎo)語:本文章記錄了本人在學(xué)習(xí)Python基礎(chǔ)之控制流程篇的重點知識及個人心得,打算入門Python的朋友們可以來一起學(xué)習(xí)并交流。 本文重點: 1、掌握異步編程的相關(guān)概念;2、了解期物future的概念、意義和使用方法;3、了解Python...
閱讀 1830·2021-11-23 09:51
閱讀 950·2021-10-08 10:05
閱讀 3434·2021-09-26 09:55
閱讀 1045·2021-09-22 15:21
閱讀 1636·2021-09-09 09:33
閱讀 1275·2019-08-30 15:56
閱讀 1287·2019-08-30 15:55
閱讀 972·2019-08-30 13:19