小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

吐血總結(jié),Python Requests庫使用指南

 LibraryPKU 2019-04-18

源 / 代碼與藝術(shù)  && 編程禪師

requests 庫是用來在Python中發(fā)出標(biāo)準(zhǔn)的HTTP請求。它將請求背后的復(fù)雜性抽象成一個(gè)漂亮,簡單的API,以便你可以專注于與服務(wù)交互和在應(yīng)用程序中使用數(shù)據(jù)。

在本文中,你將看到 requests 提供的一些有用的功能,以及如何針對你可能遇到的不同情況來自定義和優(yōu)化這些功能。你還將學(xué)習(xí)如何有效的使用 requests,以及如何防止對外部服務(wù)的請求導(dǎo)致減慢應(yīng)用程序的速度。

在本教程中,你將學(xué)習(xí)如何:

  • 使用常見的HTTP方法發(fā)送請求

  • 定制你的請求頭和數(shù)據(jù),使用查詢字符串和消息體

  • 檢查你的請求和響應(yīng)的數(shù)據(jù)

  • 發(fā)送帶身份驗(yàn)證的請求

  • 配置你的請求來避免阻塞或減慢你的應(yīng)用程序

雖然我試圖包含盡可能多的信息來理解本文中包含的功能和示例,但閱讀此文需要對HTTP有基礎(chǔ)的了解。

現(xiàn)在讓我們深入了解如何在你的應(yīng)用程序中使用請求!

開始使用 requests

讓我們首先安裝 requests 庫。為此,請運(yùn)行以下命令:

  1. pip install requests

如果你喜歡使用 Pipenv 管理Python包,你可以運(yùn)行下面的命令:

  1. pipenv install requests

一旦安裝了 requests ,你就可以在應(yīng)用程序中使用它。像這樣導(dǎo)入 requests :

  1. import requests

現(xiàn)在你已經(jīng)都準(zhǔn)備完成了,那么是時(shí)候開始使用 requests 的旅程了。你的第一個(gè)目標(biāo)是學(xué)習(xí)如何發(fā)出GET請求。


GET 請求

HTTP方法(如GET和POST)決定當(dāng)發(fā)出HTTP請求時(shí)嘗試執(zhí)行的操作。除了GET和POST之外,還有其他一些常用的方法,你將在本教程的后面部分使用到。

最常見的HTTP方法之一是GET。GET方法表示你正在嘗試從指定資源獲取或檢索數(shù)據(jù)。要發(fā)送GET請求,請調(diào)用 requests.get() 。

你可以通過下面方式來向GitHub的 Root REST API 發(fā)出GET請求:

  1. >>> requests.get( https://api.github.com )

  2. <Response [200]>

恭喜!你發(fā)出了你的第一個(gè)請求。接下來讓我們更深入地了解該請求的響應(yīng)。


響應(yīng)

Response 是檢查請求結(jié)果的強(qiáng)有力的對象。讓我們再次發(fā)出相同的請求,但這次將返回值存儲在一個(gè)變量中,以便你可以仔細(xì)查看其屬性和方法:

  1. >>> response = requests.get( https://api.github.com )

在此示例中,你捕獲了 get() 的返回值,該值是 Response 的實(shí)例,并將其存儲在名為 response 的變量中。你現(xiàn)在可以使用 response 來查看有關(guān)GET請求結(jié)果的全部信息。

狀態(tài)碼

您可以從 Response 獲取的第一部分信息是狀態(tài)碼。狀態(tài)碼會展示你請求的狀態(tài)。

例如, 200OK 狀態(tài)表示你的請求成功,而 404NOT FOUND 狀態(tài)表示找不到你要查找的資源。還有許多其它的狀態(tài)碼 ,可以為你提供關(guān)于你的請求所發(fā)生的具體情況。

通過訪問 .status_code,你可以看到服務(wù)器返回的狀態(tài)碼:

  1. >>> response.status_code

  2. 200

.status_code 返回 200 意味著你的請求是成功的,并且服務(wù)器返回你要請求的數(shù)據(jù)。

有時(shí),你可能想要在代碼中使用這些信息來做判斷:

  1. if response.status_code == 200:

  2.    print( Success! )

  3. elif response.status_code == 404:

  4.    print( Not Found. )

按照這個(gè)邏輯,如果服務(wù)器返回 200 狀態(tài)碼,你的程序?qū)⒋蛴?Success! 如果結(jié)果是 404 ,你的程序?qū)⒋蛴?NotFound. 。

requests 更進(jìn)一步為你簡化了此過程。如果在條件表達(dá)式中使用 Response 實(shí)例,則在狀態(tài)碼介于 200400 之間時(shí)將被計(jì)算為為 True ,否則為 False 。

因此,你可以通過重寫 if 語句來簡化上一個(gè)示例:

  1. if response:

  2.    print( Success! )

  3. else:

  4.    print( An error has occurred. )

技術(shù)細(xì)節(jié) : 因?yàn)?__bool__()Response 上的重載方法 ,因此真值測試才成立。

這意味著重新定義了 Response 的默認(rèn)行為,用來在確定對象的真值時(shí)考慮狀態(tài)碼。

請記住,此方法 不會驗(yàn)證 狀態(tài)碼是否等于 200 。原因是 200400 范圍內(nèi)的其他狀態(tài)代碼,例如 204NO CONTENT304NOT MODIFIED ,就意義而言也被認(rèn)為是成功的響應(yīng)。

例如, 204 告訴你響應(yīng)是成功的,但是下消息體中沒有返回任何內(nèi)容。

因此,通常如果你想知道請求是否成功時(shí),請確保使用這方便的簡寫,然后在必要時(shí)根據(jù)狀態(tài)碼適當(dāng)?shù)靥幚眄憫?yīng)。

假設(shè)你不想在 if 語句中檢查響應(yīng)的狀態(tài)碼。相反,如果請求不成功,你希望拋出一個(gè)異常。你可以使用 .raise_for_status()執(zhí)行此操作:

  1. import requests

  2. from requests.exceptions import HTTPError

  3. for url in [ https://api.github.com , https://api.github.com/invalid ]:

  4.    try:

  5.        response = requests.get(url)

  6.        # If the response was successful, no Exception will be raised

  7.        response.raise_for_status()

  8.    except HTTPError as http_err:

  9.        print(f HTTP error occurred: {http_err} )  # Python 3.6

  10.    except Exception as err:

  11.        print(f Other error occurred: {err} )  # Python 3.6

  12.    else:

  13.        print( Success! )

如果你調(diào)用 .raise_for_status(),將針對某些狀態(tài)碼引發(fā) HTTPError 異常。如果狀態(tài)碼指示請求成功,則程序?qū)⒗^續(xù)進(jìn)行而不會引發(fā)該異常。

進(jìn)一步閱讀:如果你不熟悉Python 3.6的 f-strings,我建議你使用它們,因?yàn)樗鼈兪呛喕袷交址暮梅椒ā?/span>

現(xiàn)在,你對于如何處理從服務(wù)器返回的響應(yīng)的狀態(tài)碼了解了許多。但是,當(dāng)你發(fā)出GET請求時(shí),你很少只關(guān)心響應(yīng)的狀態(tài)碼。通常,你希望看到更多。接下來,你將看到如何查看服務(wù)器在響應(yīng)正文中返回的實(shí)際數(shù)據(jù)。

響應(yīng)內(nèi)容

GET 請求的響應(yīng)通常在消息體中具有一些有價(jià)值的信息,稱為有效負(fù)載。使用 Response 的屬性和方法,你可以以各種不同的格式查看有效負(fù)載。

要以 字節(jié) 格式查看響應(yīng)的內(nèi)容,你可以使用 .content

  1. >>> response = requests.get( https://api.github.com )

  2. >>> response.content

  3. b {'current_user_url':'https://api.github.com/user','current_user_authorizations_html_url':'https://github.com/settings/connections/applications{/client_id}','authorizations_url':'https://api.github.com/authorizations','code_search_url':'https://api.github.com/search/code?q={query}{&page,per_page,sort,order}','commit_search_url':'https://api.github.com/search/commits?q={query}{&page,per_page,sort,order}','emails_url':'https://api.github.com/user/emails','emojis_url':'https://api.github.com/emojis','events_url':'https://api.github.com/events','feeds_url':'https://api.github.com/feeds','followers_url':'https://api.github.com/user/followers','following_url':'https://api.github.com/user/following{/target}','gists_url':'https://api.github.com/gists{/gist_id}','hub_url':'https://api.github.com/hub','issue_search_url':'https://api.github.com/search/issues?q={query}{&page,per_page,sort,order}','issues_url':'https://api.github.com/issues','keys_url':'https://api.github.com/user/keys','notifications_url':'https://api.github.com/notifications','organization_repositories_url':'https://api.github.com/orgs/{org}/repos{?type,page,per_page,sort}','organization_url':'https://api.github.com/orgs/{org}','public_gists_url':'https://api.github.com/gists/public','rate_limit_url':'https://api.github.com/rate_limit','repository_url':'https://api.github.com/repos/{owner}/{repo}','repository_search_url':'https://api.github.com/search/repositories?q={query}{&page,per_page,sort,order}','current_user_repositories_url':'https://api.github.com/user/repos{?type,page,per_page,sort}','starred_url':'https://api.github.com/user/starred{/owner}{/repo}','starred_gists_url':'https://api.github.com/gists/starred','team_url':'https://api.github.com/teams','user_url':'https://api.github.com/users/{user}','user_organizations_url':'https://api.github.com/user/orgs','user_repositories_url':'https://api.github.com/users/{user}/repos{?type,page,per_page,sort}','user_search_url':'https://api.github.com/search/users?q={query}{&page,per_page,sort,order}'}

雖然 .content 允許你訪問響應(yīng)有效負(fù)載的原始字節(jié),但你通常希望使用 UTF-8 等字符編碼將它們轉(zhuǎn)換為字符串。當(dāng)你訪問 .text 時(shí), response 將為你執(zhí)行此操作:

  1. >>> response.text

  2. {'current_user_url':'https://api.github.com/user','current_user_authorizations_html_url':'https://github.com/settings/connections/applications{/client_id}','authorizations_url':'https://api.github.com/authorizations','code_search_url':'https://api.github.com/search/code?q={query}{&page,per_page,sort,order}'...}'}

因?yàn)閷?bytes 解碼到 str 需要一個(gè)編碼格式,所以如果你沒有指定,請求將嘗試根據(jù)響應(yīng)頭來猜測編碼格式。你也可以在訪問 .text 之前通過 .encoding 來顯式設(shè)置編碼:

  1. >>> response.encoding = utf-8 # Optional: requests infers this internally

  2. >>> response.text

  3. {'current_user_url':'https://api.github.com/user','current_user_authorizations_html_url':'https://github.com/settings/connections/applications{/client_id}','authorizations_url':'https://api.github.com/authorizations','code_search_url':'https://api.github.com/search/code?q={query}{&page,per_page,sort,order}'...}'}

如果你看看響應(yīng),你會發(fā)現(xiàn)它實(shí)際上是序列化的 JSON 內(nèi)容。要獲取字典內(nèi)容,你可以使用 .text 獲取 str 并使用 json.loads() 對其進(jìn)行反序列化。但是,完成此任務(wù)的更簡單方法是使用 .json()

  1. >>> response.json()

  2. { current_user_url : https://api.github.com/user , current_user_authorizations_html_url : https://github.com/settings/connections/applications{/client_id} ...} }

.json() 返回值的類型是字典類型,因此你可以使用鍵值對的方式訪問對象中的值。

你可以使用狀態(tài)碼和消息體做許多事情。但是,如果你需要更多信息,例如有關(guān) response 本身的元數(shù)據(jù),則需要查看響應(yīng)頭部。

響應(yīng)頭部

響應(yīng)頭部可以為你提供有用的信息,例如響應(yīng)有效負(fù)載的內(nèi)容類型以及緩存響應(yīng)的時(shí)間限制。要查看這些頭部,請?jiān)L問 .headers

  1. >>> response.headers

  2. { Server : GitHub.com , Date : Mon, 10 Dec 2018 17:49:54 GMT , Content-Type : application/json; charset=utf-8 ,...}

.headers 返回類似字典的對象,允許你使用鍵來獲取頭部中的值。例如,要查看響應(yīng)有效負(fù)載的內(nèi)容類型,你可以訪問 Content-Type

  1. >>> response.headers[ Content-Type ]

  2. application/json; charset=utf-8

但是,這個(gè)類似于字典的頭部對象有一些特別之處。HTTP規(guī)范定義頭部不區(qū)分大小寫,這意味著我們可以訪問這些頭信息而不必?fù)?dān)心它們的大小寫:

  1. >>> response.headers[ content-type ]

  2. application/json; charset=utf-8

無論您使用 content-type 還是 Content-Type ,你都將獲得相同的值。

現(xiàn)在,你已經(jīng)學(xué)習(xí)了有關(guān) Response 的基礎(chǔ)知識。你已經(jīng)看到了它最有用的屬性和方法。讓我們退后一步,看看自定義 GET 請求時(shí)你的響應(yīng)如何變化。


查詢字符串參數(shù)

自定義 GET 請求的一種常用方法是通過URL中的 查詢字符串 參數(shù)傳遞值。要使用 get() 執(zhí)行此操作,請將數(shù)據(jù)傳遞給 params 。例如,你可以使用GitHub的Search API來查找 requests庫:

  1. import requests

  2. # Search GitHub s repositories for requests

  3. response = requests.get(

  4.     https://api.github.com/search/repositories ,

  5.    params={ q : requests+language:python },

  6. )

  7. # Inspect some attributes of the `requests` repository

  8. json_response = response.json()

  9. repository = json_response[ items ][0]

  10. print(f Repository name: {repository['name']} )  # Python 3.6+

  11. print(f Repository description: {repository['description']} )  # Python 3.6+

通過將字典 { q :requests + language:python } 傳遞給 .get()params 參數(shù),你可以修改從Search API返回的結(jié)果。

你可以像你剛才那樣以字典的形式或以元組列表形式將 params 傳遞給 get():

  1. >>> requests.get(

  2. ...     https://api.github.com/search/repositories ,

  3. ...     params=[( q , requests+language:python )],

  4. ... )

  5. <Response [200]>

你甚至可以傳 bytes 作為值:

  1. >>> requests.get(

  2. ...     https://api.github.com/search/repositories ,

  3. ...     params=b q=requests+language:python ,

  4. ... )

  5. <Response [200]>

查詢字符串對于參數(shù)化GET請求很有用。你還可以通過添加或修改發(fā)送的請求的頭部來自定義你的請求。


請求頭

要自定義請求頭,你可以使用 headers 參數(shù)將HTTP頭部組成的字典傳遞給 get()。例如,你可以通過 Accept 中指定文本匹配媒體類型來更改以前的搜索請求,以在結(jié)果中突出顯示匹配的搜索字詞:

  1. import requests

  2. response = requests.get(

  3.     https://api.github.com/search/repositories ,

  4.    params={ q : requests+language:python },

  5.    headers={ Accept : application/vnd.github.v3.text-match+json },

  6. )

  7. # View the new `text-matches` array which provides information

  8. # about your search term within the results

  9. json_response = response.json()

  10. repository = json_response[ items ][0]

  11. print(f Text matches: {repository['text_matches']} )

Accept 告訴服務(wù)器你的應(yīng)用程序可以處理哪些內(nèi)容類型。由于你希望突出顯示匹配的搜索詞,所以使用的是 application/vnd.github.v3.text-match+json,這是一個(gè)專有的GitHub的 Accept 標(biāo)頭,其內(nèi)容為特殊的JSON格式。

在你了解更多自定義請求的方法之前,讓我們通過探索其他HTTP方法來拓寬視野。


其他HTTP方法

除了 GET 之外,其他流行的HTTP方法包括 POST , `PUTDELETE, HEADPATCHOPTIONS。requests 為每個(gè)HTTP方法提供了一個(gè)方法,與 get() `具有類似的結(jié)構(gòu):

  1. >>> requests.post( https:///post , data={ key : value })

  2. >>> requests.put( https:///put , data={ key : value })

  3. >>> requests.delete( https:///delete )

  4. >>> requests.head( https:///get )

  5. >>> requests.patch( https:///patch , data={ key : value })

  6. >>> requests.options( https:///get )

調(diào)用每個(gè)函數(shù)使用相應(yīng)的HTTP方法向httpbin服務(wù)發(fā)出請求。對于每種方法,你可以像以前一樣查看其響應(yīng):

  1. >>> response = requests.head( https:///get )

  2. >>> response.headers[ Content-Type ]

  3. application/json

  4. >>> response = requests.delete( https:///delete )

  5. >>> json_response = response.json()

  6. >>> json_response[ args ]

  7. {}

每種方法的響應(yīng)中都會返回頭部,響應(yīng)正文,狀態(tài)碼等。接下來,你將進(jìn)一步了解 POST`PUTPATCH 方法,并了解它們與其他請求類型的區(qū)別。


消息體

根據(jù)HTTP規(guī)范, POST, `PUT和不太常見的 PATCH請求通過消息體而不是通過查詢字符串參數(shù)傳遞它們的數(shù)據(jù)。使用 requests,你將有效負(fù)載傳遞給相應(yīng)函數(shù)的 data 參數(shù)。

data 接收字典,元組列表,字節(jié)或類文件對象。你需要將在請求正文中發(fā)送的數(shù)據(jù)調(diào)整為與你交互的服務(wù)的特定格式。

例如,如果你的請求的內(nèi)容類型是 application/x-www-form-urlencoded ,則可以將表單數(shù)據(jù)作為字典發(fā)送:

  1. >>> requests.post( https:///post , data={ key : value })

  2. <Response [200]>

你還可以將相同的數(shù)據(jù)作為元組列表發(fā)送:

  1. >>> requests.post( https:///post , data=[( key , value )])

  2. <Response [200]>

但是,如果需要發(fā)送JSON數(shù)據(jù),則可以使用 json 參數(shù)。當(dāng)你通過 json 傳遞JSON數(shù)據(jù)時(shí), requests 將序列化你的數(shù)據(jù)并為你添加正確的 Content-Type 標(biāo)頭。

requests 作者 Kenneth Reitz 創(chuàng)建的一個(gè)很好的資源。它是一種接收測試請求并響應(yīng)有關(guān)請求數(shù)據(jù)的服務(wù)。例如,你可以使用它來檢查基本的POST請求:

  1. >>> response = requests.post( https:///post , json={ key : value })

  2. >>> json_response = response.json()

  3. >>> json_response[ data ]

  4. {'key': 'value'}

  5. >>> json_response[ headers ][ Content-Type ]

  6. application/json

你可以從響應(yīng)中看到服務(wù)器在你發(fā)送請求時(shí)收到了請求數(shù)據(jù)和標(biāo)頭。requests 還以 PreparedRequest 的形式向你提供此信息。


檢查你的請求

當(dāng)你發(fā)出請求時(shí), requests 庫會在將請求實(shí)際發(fā)送到目標(biāo)服務(wù)器之前準(zhǔn)備該請求。請求準(zhǔn)備包括像驗(yàn)證頭信息和序列化JSON內(nèi)容等。

你可以通過訪問 .request 來查看 PreparedRequest:

  1. >>> response = requests.post( https:///post , json={ key : value })

  2. >>> response.request.headers[ Content-Type ]

  3. application/json

  4. >>> response.request.url

  5. https:///post

  6. >>> response.request.body

  7. b {'key': 'value'}

通過檢查 PreparedRequest ,你可以訪問有關(guān)正在進(jìn)行的請求的各種信息,例如有效負(fù)載,URL,頭信息,身份驗(yàn)證等。

到目前為止,你已經(jīng)發(fā)送了許多不同類型的請求,但它們都有一個(gè)共同點(diǎn):它們是對公共API的未經(jīng)身份驗(yàn)證的請求。你遇到的許多服務(wù)可能都希望你以某種方式進(jìn)行身份驗(yàn)證。


身份驗(yàn)證

身份驗(yàn)證可幫助服務(wù)了解你的身份。通常,你通過將數(shù)據(jù)傳遞到 Authorization 頭信息或服務(wù)定義的自定義頭信息來向服務(wù)器提供憑據(jù)。你在此處看到的所有請求函數(shù)都提供了一個(gè)名為 auth 的參數(shù),允許你傳遞憑據(jù)。

需要身份驗(yàn)證的一個(gè)示例API的是GitHub的 Authenticated User API。此端點(diǎn)提供有關(guān)經(jīng)過身份驗(yàn)證的用戶配置文件的信息。要向 AuthenticatedUserAPI 發(fā)出請求,你可以將你的GitHub的用戶名和密碼以元組傳遞給 get()

  1. >>> from getpass import getpass

  2. >>> requests.get( https://api.github.com/user , auth=( username , getpass()))

  3. <Response [200]>

如果你在元組中傳遞給 auth 的憑據(jù)有效,則請求成功。如果你嘗試在沒有憑據(jù)的情況下發(fā)出此請求,你將看到狀態(tài)代碼為 401Unauthorized :

  1. >>> requests.get( https://api.github.com/user )

  2. <Response [401]>

當(dāng)你以元組形式吧用戶名和密碼傳遞給 auth 參數(shù)時(shí), rqeuests 將使用HTTP的基本訪問認(rèn)證方案來應(yīng)用憑據(jù)。

因此,你可以通過使用 HTTPBasicAuth 傳遞顯式的基本身份驗(yàn)證憑據(jù)來發(fā)出相同的請求:

  1. >>> from requests.auth import HTTPBasicAuth

  2. >>> from getpass import getpass

  3. >>> requests.get(

  4. ...     https://api.github.com/user ,

  5. ...     auth=HTTPBasicAuth( username , getpass())

  6. ... )

  7. <Response [200]>

雖然你不需要明確進(jìn)行基本身份驗(yàn)證,但你可能希望使用其他方法進(jìn)行身份驗(yàn)證。requests提供了開箱即用的其他身份驗(yàn)證方法,例如 HTTPDigestAuthHTTPProxyAuth 。

你甚至可以提供自己的身份驗(yàn)證機(jī)制。為此,你必須首先創(chuàng)建AuthBase的子類。然后,實(shí)現(xiàn) __call __()

  1. import requests

  2. from requests.auth import AuthBase

  3. class TokenAuth(AuthBase):

  4.    '''Implements a custom authentication scheme.'''

  5.    def __init__(self, token):

  6.        self.token = token

  7.    def __call__(self, r):

  8.        '''Attach an API token to a custom auth header.'''

  9.        r.headers[ X-TokenAuth ] = f {self.token}  # Python 3.6+

  10.        return r

  11. requests.get( https:///get , auth=TokenAuth( 12345abcde-token ))

在這里,你自定義的 TokenAuth 接收一個(gè)令牌,然后在你的請求頭中的 X-TokenAuth 頭中包含該令牌。

錯(cuò)誤的身份驗(yàn)證機(jī)制可能會導(dǎo)致安全漏洞,因此,除非服務(wù)因某種原因需要自定義身份驗(yàn)證機(jī)制,否則你始終希望使用像 BasicOAuth 這樣經(jīng)過驗(yàn)證的身份驗(yàn)證方案。

在考慮安全性時(shí),讓我們考慮使用 requests 處理SSL證書。


SSL證書驗(yàn)證

每當(dāng)你嘗試發(fā)送或接收的數(shù)據(jù)都很敏感時(shí),安全性就很重要。通過HTTP與站點(diǎn)安全通信的方式是使用SSL建立加密連接,這意味著驗(yàn)證目標(biāo)服務(wù)器的SSL證書至關(guān)重要。

好消息是 requests 默認(rèn)為你執(zhí)行此操作。但是,在某些情況下,你可能希望更改此行為。

如果要禁用SSL證書驗(yàn)證,請將 False 傳遞給請求函數(shù)的 verify 參數(shù):

  1. >>> requests.get( https://api.github.com , verify=False)

  2. InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings

  3.  InsecureRequestWarning)

  4. <Response [200]>

當(dāng)你提出不安全的請求時(shí), requests 甚至?xí)l(fā)出警告來幫助你保護(hù)數(shù)據(jù)安全。


性能

在使用 requests 時(shí),尤其是在生產(chǎn)應(yīng)用程序環(huán)境中,考慮性能影響非常重要。超時(shí)控制,會話和重試限制等功能可以幫助你保持應(yīng)用程序平穩(wěn)運(yùn)行。

超時(shí)控制

當(dāng)你向外部服務(wù)發(fā)出請求時(shí),系統(tǒng)將需要等待響應(yīng)才能繼續(xù)。如果你的應(yīng)用程序等待響應(yīng)的時(shí)間太長,則可能會阻塞對你的服務(wù)的請求,你的用戶體驗(yàn)可能會受到影響,或者你的后臺作業(yè)可能會掛起。

默認(rèn)情況下, requests 將無限期地等待響應(yīng),因此你幾乎應(yīng)始終指定超時(shí)時(shí)間以防止這些事情發(fā)生。要設(shè)置請求的超時(shí),請使用 timeout 參數(shù)。timeout 可以是一個(gè)整數(shù)或浮點(diǎn)數(shù),表示在超時(shí)之前等待響應(yīng)的秒數(shù):

  1. >>> requests.get( https://api.github.com , timeout=1)

  2. <Response [200]>

  3. >>> requests.get( https://api.github.com , timeout=3.05)

  4. <Response [200]>

在第一個(gè)請求中,請求將在1秒后超時(shí)。在第二個(gè)請求中,請求將在3.05秒后超時(shí)。

你還可以將元組傳遞給 timeout,第一個(gè)元素是連接超時(shí)(它允許客戶端與服務(wù)器建立連接的時(shí)間),第二個(gè)元素是讀取超時(shí)(一旦你的客戶已建立連接而等待響應(yīng)的時(shí)間):

  1. >>> requests.get( https://api.github.com , timeout=(2, 5))

  2. <Response [200]>

如果請求在2秒內(nèi)建立連接并在建立連接的5秒內(nèi)接收數(shù)據(jù),則響應(yīng)將按原樣返回。如果請求超時(shí),則該函數(shù)將拋出 Timeout 異常:

  1. import requests

  2. from requests.exceptions import Timeout

  3. try:

  4.    response = requests.get( https://api.github.com , timeout=1)

  5. except Timeout:

  6.    print( The request timed out )

  7. else:

  8.    print( The request did not time out )

你的程序可以捕獲 Timeout 異常并做出相應(yīng)的響應(yīng)。

Session對象

到目前為止,你一直在處理高級請求API,例如 get()post()。這些函數(shù)是你發(fā)出請求時(shí)所發(fā)生的事情的抽象。為了你不必?fù)?dān)心它們,它們隱藏了實(shí)現(xiàn)細(xì)節(jié),例如如何管理連接。

在這些抽象之下是一個(gè)名為 Session 的類。如果你需要微調(diào)對請求的控制方式或提高請求的性能,則可能需要直接使用 Session 實(shí)例。

Session 用于跨請求保留參數(shù)。例如,如果要跨多個(gè)請求使用相同的身份驗(yàn)證,則可以使用 session

  1. import requests

  2. from getpass import getpass

  3. # By using a context manager, you can ensure the resources used by

  4. # the session will be released after use

  5. with requests.Session() as session:

  6.    session.auth = ( username , getpass())

  7.    # Instead of requests.get(), you ll use session.get()

  8.    response = session.get( https://api.github.com/user )

  9. # You can inspect the response just like you did before

  10. print(response.headers)

  11. print(response.json())

每次使用 session 發(fā)出請求時(shí),一旦使用身份驗(yàn)證憑據(jù)初始化,憑據(jù)將被保留。

session 的主要性能優(yōu)化以持久連接的形式出現(xiàn)。當(dāng)你的應(yīng)用程序使用 Session 建立與服務(wù)器的連接時(shí),它會在連接池中保持該連接。當(dāng)你的應(yīng)用程序想要再次連接到同一服務(wù)器時(shí),它將重用池中的連接而不是建立新連接。

最大重試

請求失敗時(shí),你可能希望應(yīng)用程序重試相同的請求。但是,默認(rèn)情況下, requests 不會為你執(zhí)行此操作。要應(yīng)用此功能,您需要實(shí)現(xiàn)自定義 Transport Adapter。

通過 TransportAdapters,你可以為每個(gè)與之交互的服務(wù)定義一組配置。例如,假設(shè)你希望所有對于https://api.github.com的請求在最終拋出 ConnectionError 之前重試三次。你將構(gòu)建一個(gè) TransportAdapter,設(shè)置其 max_retries 參數(shù),并將其裝載到現(xiàn)有的 Session

  1. import requests

  2. from requests.adapters import HTTPAdapter

  3. from requests.exceptions import ConnectionError

  4. github_adapter = HTTPAdapter(max_retries=3)

  5. session = requests.Session()

  6. # Use `github_adapter` for all requests to endpoints that start with this URL

  7. session.mount( https://api.github.com , github_adapter)

  8. try:

  9.    session.get( https://api.github.com )

  10. except ConnectionError as ce:

  11.    print(ce)

當(dāng)您將 HTTPAdapter(github_adapter)掛載到 session 時(shí), session將遵循其對https://api.github.com的每個(gè)請求的配置。

TimeoutsTransportAdaptersSessions 用于保持代碼高效和應(yīng)用程序的魯棒性。


總結(jié)

在學(xué)習(xí)Python中強(qiáng)大的 requests 庫方面,你已經(jīng)走了很長的路。

你現(xiàn)在能夠:

  • 使用各種不同的HTTP方法發(fā)出請求,例如GET,POST和PUT

  • 通過修改請求頭,身份驗(yàn)證,查詢字符串和消息體來自定義你的請求

  • 檢查發(fā)送到服務(wù)器的數(shù)據(jù)以及服務(wù)器發(fā)回給你的數(shù)據(jù)

  • 使用SSL證書驗(yàn)證

  • 高效的使用 requests 通過使用 max_retries, timeout, Sessions 和 TransportAdapters

因?yàn)槟鷮W(xué)會了如何使用 requests,所以你可以使用他們提供的迷人數(shù)據(jù)探索廣泛的Web服務(wù)世界并構(gòu)建出色的應(yīng)用程序了。

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約