首先,我列出了最近一年內(nèi)PyPI上下載量最高的Python包?,F(xiàn)在我們來看看這些包的作用,他們之間的關(guān)系,以及為什么如此流行。
Urllib3 是 Python 的 HTTP 客戶端,它提供了許多 Python 標(biāo)準(zhǔn)庫沒有的功能。盡管名字叫做 Urllib3,但它并不是 Python 自帶的 urllib2 的后繼版本。如果你想盡可能使用 Python 的核心功能(比如由于某些限制導(dǎo)致不能安裝),那么可以看看 urllib.request。對于最終用戶,我強(qiáng)烈推薦 requests 包(參考列表中的第六項)。Urllib3 之所以排名第一是因為幾乎 1200 個軟件包都依賴它,許多這些軟件包也都在列表中名列前茅。Six 是 Python 2 和 Python 3 兼容性工具。該項目的目的是讓代碼能夠同時在 Python 2 和 ?Python 3 上運(yùn)行。它提供了許多函數(shù),掩蓋了 Python 2 和 ?Python 3 之間的語法差異。最容易理解的例子就是six.print_()。在 Python 3 中,輸出時需要使用 print() 函數(shù),而 Python 2 中是使用不帶括號的 print。因此,使用 six.print_() 可以同時支持兩種語言。?盡管我理解該包如此流行,但還是希望人們盡快拋棄 Python 2,特別是從2020年1月1日起官方已經(jīng)不再支持 Python 2了。3. botocore, boto3, s3transfer, awsclibotocore:第3名,6.6億次下載
s3transfer:第7名,5.84億次下載
awscli:第17名,3.94億次下載
boto3:第22名,3.29億次下載
Botocore 是 AWS 的底層接口。botocore 是 boto3(第22名)庫的基礎(chǔ),后者可以讓你訪問亞馬遜的S3、EC2等服務(wù)。Botocore 也是 AWS-CLI 的基礎(chǔ),后者是 AWS 的命令行界面。s3transfer(第七名)是用于管理S3傳輸?shù)?Python 庫。該庫仍在開發(fā)中,它的主頁依然不建議使用,或者使用時至少要固定版本,因為即使在小版本號之間它的API也可能會發(fā)生變化。boto3、AWS-CLI 和許多其他項目都依賴于 s3transfer。AWS 相關(guān)的庫的排名如此高,正說明了 AWS 的服務(wù)是多么流行。我猜許多人都知道并且喜愛 pip(Python的包安裝工具)。使用 pip 從 Python Package Index和其他倉庫(如本地鏡像或包含私有軟件的自定義倉庫等)安裝軟件包不費吹灰之力。Pip 的名字是個遞歸定義:Pip Installs Packages
Pip 非常容易使用。安裝一個軟件包只需要執(zhí)行 pip install <軟件包名>。刪除只需要執(zhí)行 pip uninstall <軟件包名>。
Pip 最大的好處就是它可以安裝一系列包,通常會放在 requirements.txt 文件中。該文件還可以指定每個包的詳細(xì)版本號。絕大多數(shù) Python 項目都會包含這個文件。
與 virtualenv(第57名)結(jié)合使用 pip,可以創(chuàng)建可預(yù)測的、獨立的環(huán)境,而不會與系統(tǒng)本身的環(huán)境互相影響。
Python-dateutil 模塊為標(biāo)準(zhǔn)的 datetime 模塊提供了強(qiáng)大的功能擴(kuò)展。普通的 Python datetime 無法做到的事情都可以使用 python-dateutil 完成。?用這個庫可以完成許多非??岬墓δ?。我只舉一個非常有用的例子:從日志文件中模糊解析日期字符串:from?dateutil.parser?import?parse
logline?=? INFO?2020-01-01T00:00:01?Happy?new?year,?human.
timestamp?=?parse(log_line,?fuzzy=True)
print(timestamp)
#?2020-01-01?00:00:01
Requests 基于下載量第一的庫 urllib3。有了它,發(fā)送請求變得極其簡單。許多人對 requests 的喜愛超過了 urllib3,因此 requets 的最終用戶可能比 urllib3 還要多。后者更底層,通常作為其他項目的依賴出現(xiàn)。下面的例子演示了 requests 有多么容易使用:import?requests
r?=?requests.get( https://api.github.com/user ,?auth=( user ,? pass ))
r.status_code
#?200
r.headers[ content-type ]
#? application/json;?charset=utf8
r.encoding
#? utf-8
r.text
#?u {"type":"User"...
r.json()
#?{u disk_usage :?368627,?u private_gists :?484,?...}
第3、7、17和22名互相關(guān)聯(lián),所以請參見第3名的介紹。近年來,幾乎所有網(wǎng)站都開始使用SSL,這一點可以從地址欄中的鎖圖標(biāo)看出來,該圖標(biāo)的意思是網(wǎng)站是安全的、加密的,可以避免竊聽。加密基于SSL證書,SSL證書由可信的公司或非營利組織負(fù)責(zé)簽發(fā),如 LetsEncrypt。這些組織會對利用它們的證書對簽發(fā)的證書進(jìn)行數(shù)字簽名。利用這些證書的公開部分,瀏覽器就可以驗證網(wǎng)站的簽名,從而證明你訪問的是真正的網(wǎng)站,而且別人沒有在竊聽數(shù)據(jù)。Python 也可以做到同樣的功能,這就需要用到 certifi。它和 Chrome、Firefox 和 Edge 等Web瀏覽器中包含的根證書集合沒有什么區(qū)別。Certifi 是一個根證書集合,這樣 Python 代碼就可以驗證SSL證書的可信度。許多項目都信賴并依賴 certifi,可以在這里看到這些項目。這也是為何該項目排名如此高的原因。根據(jù) PyPI 的頁面,idna提供“對于RFC5891中定義的IDNA協(xié)議(Internationalised Domain Names in Applications)的支持”。IDNA 是處理包含非 ASCII 字符的域名的規(guī)則。但原始的域名不是已經(jīng)支持非 ASCII 字符了嗎?那么問題何在?問題是許多應(yīng)用程序(如Email客戶端和Web瀏覽器等)并不支持非 ASCII 字符。或者更具體地說,Email 和 HTTP 協(xié)議并不支持這些字符。在許多國家這并不是問題,但像中國、俄羅斯、德國、印尼等國家就很不方便。因此,這些國家的一些聰明人聯(lián)合起來提出了 IDNA,也并非完全偶然。IDNA 的核心是兩個函數(shù):ToASCII 和 ToUnicode。ToASCCI 會將國際化的 Unicode 域名轉(zhuǎn)換成 ASCII 字符串,而 ToUnicode 會做相反的處理。在 IDNA 包中,這兩個函數(shù)叫做 idna.encode() 和 idna.decode(),參見下面的例子:import?idna
idna.encode( ドメイン.テスト )
#?b xn--eckwd4c7c.xn--zckzah
print(idna.decode( xn--eckwd4c7c.xn--zckzah ))
#?ドメイン.テスト
該編碼的詳細(xì)內(nèi)容可以參見 RFC3490。YAML 是一種數(shù)據(jù)序列化格式。它的設(shè)計目標(biāo)是同時方便人類和機(jī)器閱讀——人類很容易讀懂,計算機(jī)解析也不難。PyYAML 是 Python 的 YAM 解析器和編碼器,也就是說它可以讀寫 YAML 格式。它可以將任何 Python 對象編碼為 YAML:列表,字典,甚至類實例都可以。Python 提供了自己的配置管理器,但 YAML 提供的功能遠(yuǎn)勝于 Python 自帶的 ConfigParser(只能使用最基本的.ini文件)。例如,YAML 能存儲任何數(shù)據(jù)類型:boolean,list,float等。ConfigParse 的內(nèi)部一切都保存為字符串。如果你要用 ConfigParser 來加載證書,就需要指明你需要的是整數(shù):config.getint(“section”,?“my_int”)
而 pyyaml 能夠自動識別類型,因此只需這樣就能獲得 int:config[“section”][“my_int”]
YAML 還允許任意深度的嵌套,盡管并非每個項目都需要,但非常方便。你可以自行決定使用哪一個,但許多項目都使用 YAML 作為配置文件,因此該項目的流行度非常高。像 IDNA 一樣,這個項目的描述的信息量也非常大:?ASN.1 類型和 DER/BER/CER 編碼(X.208)的純 Python 實現(xiàn)。幸運(yùn)的是,我們依然能找到這個幾十年之久的標(biāo)準(zhǔn)的許多資料。ASN.1 是 Abstract Syntax Notation One(抽象語法記法一)的縮寫,是數(shù)據(jù)序列化的鼻祖。它來自于通訊行業(yè)。也許你知道 protocol buffer 或者 Apache Thrift 吧?ASN.1正是它們的1984年版本。ASN.1 描述了一種不同系統(tǒng)之間的跨平臺的接口,可以通過該接口發(fā)送數(shù)據(jù)結(jié)構(gòu)。還記得第8名的 certifi 嗎?ASN.1 用于定義 HTTPS 協(xié)議以及許多其他加密系統(tǒng)中使用的證書的格式。ASN.1 還廣泛用于 SNMP、LDAP、Kerberos、UMTS、LTE 和 VOIP 等協(xié)議中。它是個非常復(fù)雜的標(biāo)準(zhǔn),人們已經(jīng)發(fā)現(xiàn)某些實現(xiàn)充滿了脆弱性。你可以看看 Reddit 上的這個關(guān)于 ASN.1 的討論(https://www.reddit.com/r/programming/comments/1hf7ds/useful_old_technologies_asn1/)。除非真正必要,否則我建議不要使用它。但由于許多地方都在使用該協(xié)議,因此許多包都依賴于它。Docutils 是一個模塊化系統(tǒng),用于將純文本文檔轉(zhuǎn)換成其他格式,如 HTML、XML 和 LaTeX等。docutils 可以讀取 reStructuredText 格式(一種類似于 MarkDown 的容易閱讀的格式)的純文本文檔。我猜你一定聽說過 PEP 文檔,甚至可能閱讀過。PEP 文檔是什么?PEP 的意思是 Python Enhanced Proposal(Python增強(qiáng)提案)。PEP 是一篇設(shè)計文檔,用于給 Pytho n社區(qū)提供信息,或者為 Python(或其處理器、環(huán)境)描述一個新特性。PEP 應(yīng)該提供特性的精確的技術(shù)標(biāo)準(zhǔn),并給出該特性的理由。PEP 文檔就是使用固定的 reStructuredText 模板,然后通過 docutils 轉(zhuǎn)換成漂亮的文檔。Sphinx 的核心也使用了 docutils。Sphinx 用于創(chuàng)建文檔項目。如果說 docutils 是一臺機(jī)器,那么 Sphinx 就是一個工廠。它的最初設(shè)計目的是構(gòu)建P ython 本身的文檔,但許多其他項目也利用 Sphinx 來創(chuàng)建文檔。你一定讀過 readthedocs.org 上的文檔吧?那里的文檔都是使用 Sphinx 和 docutils 創(chuàng)建的。你可以使用 chardet 模塊來檢查文件或數(shù)據(jù)流的字符集。在分析大量隨機(jī)的文本時這個功能非常有用。但也可以用來判斷遠(yuǎn)程下載的數(shù)據(jù)的字符串。在安裝 chardet 后,就可以使用命令行工具 chardetect,使用方法如下:chardetect?somefile.txt
somefile.txt:?ascii?with?confidence?1.0
也可以在程序中使用該庫,參見文檔(https://chardet.readthedocs.io/en/latest/usage.html)。Requests 和許多其他包都依賴于 chardet。我估計不會有太多人直接使用 chardet,所以它的流行度肯定是來自于這些依賴。Rsa是 RSA 的純 Python 實現(xiàn)。它支持如下功能:它可以作為 Python 庫使用,也可以在命令行上使用。RSA 名稱中的三個字母來自于三個人的姓:Ron Rivest,Adi Shamir,和Leonard Adleman。他們于1977年發(fā)明了該算法。
RSA 是最早出現(xiàn)的一批公鑰加密系統(tǒng),廣泛用于安全數(shù)據(jù)傳輸。這種加密系統(tǒng)包括兩個秘鑰:一個是公鑰,一個是私鑰。使用公鑰加密數(shù)據(jù),然后該數(shù)據(jù)只能用私鑰進(jìn)行解密。
RSA 算法很慢。通常并不使用 RSA 算法直接加密用戶數(shù)據(jù),而是用它來加密對稱加密系統(tǒng)中使用的共享秘鑰,因為對稱加密系統(tǒng)速度很快,適合用來加密大量數(shù)據(jù)。
import?rsa
#?Bob?creates?a?key?pair:
(bob_pub,?bob_priv)?=?rsa.newkeys(512)
#?Alice?ecnrypts?a?message?for?Bob
#?with?his?public?key
crypto?=?rsa.encrypt( hello?Bob! ,?bob_pub)
#?When?Bob?gets?the?message,?he
#?decrypts?it?with?his?private?key:
message?=?rsa.decrypt(crypto,?bob_priv)
print(message.decode( utf8 ))
#?hello?Bob!
假設(shè) Bob 擁有私鑰 private,Alice 就能確信只有 Bob 才能閱讀該信息。但 Bob 并不能確信 Alice 是信息的發(fā)送者,因為任何人都可以獲得 Bob 的公鑰。為了證明發(fā)送者的確是 Alice,她可以使用自己的私鑰對信息進(jìn)行簽名。Bob 可以使用 Alice 的公鑰對簽名進(jìn)行驗證,來確保發(fā)送者的確是 Alice。許多其他包都依賴于 rsa,如 google-auth(第37名),oauthlib(第54名),awscli(第17名)。這個包并不會經(jīng)常被直接使用,因為有許多更快、更原生的方法。在 Python 中使用 JSON 很容易,因為 JSON 可以完美地映射到 Python 的字典上。我認(rèn)為這是最好的特性之一。說實話我從來沒聽說過 jmepath 這個包,盡管我使用過很多 JSON。我會使用 json.loads() 然后手動從字典中讀取數(shù)據(jù),或許還得寫幾個循環(huán)。JMESPath,讀作“James path”,能更容易地在 Python 中使用 JSON。你可以用聲明的方式定義怎樣從 JSON 文檔中讀取數(shù)據(jù)。下面是一些最基本的例子:?import?jmespath
#?Get?a?specific?element
d?=?{"foo":?{"bar":?"baz"}}
print(jmespath.search( foo.bar ,?d))
#?baz
#?Using?a?wildcard?to?get?all?names
d?=?{"foo":?{"bar":?[{"name":?"one"},?{"name":?"two"}]}}
print(jmespath.search( foo.bar[*].name ,?d))
#?[“one”,?“two”]
這僅僅是它的冰山一角。更多用法參見它的文檔和 PyPI 主頁。Setuptools 是用來創(chuàng)建 Python 包的工具。這個項目的文檔很糟糕。文檔并沒有描述它的功能,還包含死鏈接。真正的好文檔在這里:https://packaging.python.org/,以及這篇文章中關(guān)于怎樣創(chuàng)建 Python 包的教程:https://packaging.python.org/tutorials/packaging-projects/。第3、7、17和22名互相關(guān)聯(lián),所以請參見第3名的介紹。類似于第5名的 dateutils,該庫可以幫助你操作日期和時間。處理時區(qū)很麻煩。幸運(yùn)的是,這個包可以讓時區(qū)處理變得很容易。關(guān)于時間,我的經(jīng)驗是:在內(nèi)部永遠(yuǎn)使用UTC,只有在需要產(chǎn)生供人閱讀的輸出時才轉(zhuǎn)換成本地時間。from?datetime?import?datetime
from?pytz?import?timezone
amsterdam?=?timezone( Europe/Amsterdam )
ams_time?=?amsterdam.localize(datetime(2002,?10,?27,?6,?0,?0))
print(ams_time)
#?2002-10-27?06:00:00+01:00
#?It?will?also?know?when?it s?Summer?Time
#?in?Amsterdam?(similar?to?Daylight?Savings?Time):
ams_time?=?amsterdam.localize(datetime(2002,?6,?27,?6,?0,?0))
print(ams_time)
#?2002-06-27?06:00:00+02:00
從 Python 3.2 開始,python 開始提供 concurrent.futures 模塊,可以幫你執(zhí)行異步操作。futures 包是該庫的反向移植,所以它是用于 Python 2 的。當(dāng)前的 Python 3 版本不需要該包,因為 Python 3 本身就提供了該功能。前面我說過,從2020年1月1日起官方已經(jīng)停止支持 Python 2。我希望明年再做這個列表的時候,不再看到這個包排進(jìn)前22名。from?concurrent.futures?import?ThreadPoolExecutor
from?time?import?sleep
def?return_after_5_secs(message):
??sleep(5)
??return?message
pool?=?ThreadPoolExecutor(3)
future?=?pool.submit(return_after_5_secs,?
?????????????????????("Hello?world"))
print(future.done())
#?False
sleep(5)
print(future.done())
#?True
print(future.result())
#?Hello?World
可見,我們可以創(chuàng)建一個線程池,然后提交一個函數(shù),讓某個線程執(zhí)行。同時,你的程序會繼續(xù)在主線程上運(yùn)行。這是實現(xiàn)并行執(zhí)行的一種很容易的方式。下面的示例演示了實現(xiàn)這個功能有多么容易:from?colorama?import?Fore,?Back,?Style
print(Fore.RED?+? some?red?text )
print(Back.GREEN?+? and?with?a?green?background )
print(Style.DIM?+? and?in?dim?text )
print(Style.RESET_ALL)
print( back?to?normal?now )
Python 自帶的 json 模塊有什么問題導(dǎo)致了這個包有如此高的排名?沒有任何問題!實際上, Python 的 json 就是 simplejson。但 simplejson 有一些優(yōu)點:try:
??import?simplejson?as?json
except?ImportError:
??import?json
不過,除非確實需要一些標(biāo)準(zhǔn)庫中沒有的功能,我依然會使用 json。SImplejson 可能比 json快很多,因為它的一部分是用C實現(xiàn)的。但是除非你要處理幾千個 JSON 文件,否則這點速度提升并不明顯。此外還可以看看 UltraJSON,這是個幾乎完全用C編寫的包,應(yīng)該速度更快。第3、7、17和22名互相關(guān)聯(lián),所以請參見第3名的介紹。只寫22個包很難,因為后面的許多包都是終端用戶更傾向使用的包。許多排名靠前的包提供一些核心的功能,如處理時間、配置文件、加密和標(biāo)準(zhǔn)化等。它們通常是其他項目的依賴。
最常見的使用場景就是連接。許多包提供的功能就是連接到服務(wù)器,或者支持其他包連接服務(wù)器。
其他包是對 Python 的擴(kuò)展,比如用于創(chuàng)建 Python 包的工具,創(chuàng)建文檔的工具,創(chuàng)建版本兼容性的工具,等等。