微吼云上線多路互動直播服務 加速多場景互動直播落地
801
2025-03-31
目錄
用于可視化調試的 pudb
與pudb交互
使用監視表達式并訪問 REPL
為什么 pudb 很棒
與 Web 交互的請求
請求是可讀的
請求是強大的
為什么請求很棒
解析匹配字符串
查找匹配給定模式的字符串
使用格式說明符
訪問底層正則表達式
為什么解析很棒
dateutil 用于處理日期和時間
設置時區
解析日期和時間字符串
計算時差
計算重復事件
為什么 dateutil 很棒
用于命令行界面解析的打字機
argparse 很笨重
為什么打字機很棒
結論:五個有用的 Python 包
Python 擁有龐大的包、模塊和庫生態系統,您可以使用它們來創建應用程序。其中一些包和模塊包含在您的 Python 安裝中,統稱為標準庫。
標準庫由為常見編程問題提供標準化解決方案的模塊組成。它們是跨許多學科的應用程序的絕佳構建塊。但是,許多開發人員更喜歡使用替代包或擴展,這可能會提高標準庫中內容的可用性和實用性。
您將在本教程中學習的包是:
pudb:一個先進的、基于文本的可視化調試器
requests:用于發出 HTTP 請求的漂亮 API
parse:一個直觀、可讀的文本匹配器
dateutil:流行datetime庫的擴展
typer:直觀的命令行界面解析器
您將首先查看pdb.
pudb?用于可視化調試
我花了很多時間通過SSH 連接到遠程機器,所以我無法利用大多數IDE。我選擇的調試器是pudb,它有一個基于文本的用戶界面。我發現它的界面直觀且易于使用。
Python 附帶pdb, 其靈感來自gdb,其本身靈感來自dbx.?雖然可以pdb完成這項工作,但它最強大的功能是它附帶了 Python。因為它是基于命令行的,所以你要記住很多快捷鍵,一次只能看到少量的源代碼。
另一個用于調試的 Python 包是pudb.?它顯示源代碼的全屏以及有用的調試信息。它的另一個好處是讓我懷念過去在Turbo Pascal 中編碼的日子:
界面分為兩個主要部分。左側面板用于源代碼,右側面板用于上下文信息。右側分為三個部分:
Variables
Stack
Breakpoints
您在調試器中需要的一切都在一個屏幕上可用。
互動?pudb
您可以pudb通過pip以下方式安裝:
$ python -m pip install pudb
如果您使用的是 Python 3.7 或更高版本,那么您可以breakpoint()通過將PYTHONBREAKPOINT環境變量設置為pudb.set_trace.?如果您使用的是基于 Unix 的操作系統,例如 Linux 或 macOS,那么您可以按如下方式設置變量:
$ export PYTHONBREAKPOINT=pudb.set_trace
如果您使用的是 Windows,則命令會有所不同:
C:\> set PYTHONBREAKPOINT=pudb.set_trace
或者,您可以import pudb; pudb.set_trace()直接插入到您的代碼中。
當您運行的代碼遇到斷點時,會pudb中斷執行并顯示其界面:
您可以使用鍵盤導航和執行源代碼:
如果您重新啟動代碼,則會pudb記住上一個會話中的斷點。Right并Left允許您在右側的源代碼和控制區域之間移動。
在Variables框中,您會看到當前范圍內的所有變量:
默認情況下,變量的視圖被縮短,但您可以通過按 來查看完整內容\。展開視圖將顯示元組或列表中的項目,或者顯示二進制變量的完整內容。T和R來回切換之間repr和type顯示模式。
使用監視表達式并訪問 REPL
當右側的變量區域聚焦時,您還可以添加監視表達式。watch 可以是任何 Python 表達式。當對象仍處于其縮短形式時,它對于檢查深埋在對象中的數據或評估變量之間的復雜關系非常有用。
注意:您可以通過按 來添加監視表達式N。由于N也用于執行當前代碼行,因此在按下該鍵之前,您必須確保屏幕的正確區域處于焦點。
!在當前正在運行的程序的上下文中,按下會使您轉義到 REPL。此模式還會向您顯示在調試器觸發之前發送到屏幕的任何輸出。通過導航界面或使用快捷鍵,您還可以修改斷點、更改您在堆棧幀中的位置以及加載其他源代碼文件。
為什么pudb很棒
該pudb界面需要更少的快捷鍵記憶,pdb并且旨在顯示盡可能多的代碼。它具有IDE中調試器的大部分功能,但可以在終端中使用。由于這個 Python 包的安裝只需很短的pip時間,您可以快速將其帶入任何環境。下次你被命令行卡住時,檢查一下!
requests?用于與 Web 交互
我從標準庫之外挑選的 Python 包的第一選擇是流行的requests包。它在我的計算機上具有特殊地位,因為它是我在系統范圍內安裝的唯一外部軟件包。所有其他軟件包都位于其專用的虛擬環境中。
我并不是唯一一個喜歡requests作為 Python Web 交互的主要工具的人:根據requests?文檔,該軟件包每天的下載量約為 160 萬次!
這個數字如此之高是因為與 Internet 的程序化交互提供了許多可能性,無論是通過Web API發布您的文章還是通過Web 抓取獲取數據。但是 Python 的標準庫已經包含了urllib幫助完成這些任務的包。那么為什么要使用外部包呢?是什么造就了requests如此受歡迎的選擇?
requests?可讀
該requests庫提供了一個開發良好的 API,它緊密遵循 Python 的目標,即像普通英語一樣可讀。該requests開發者總結了他們的口號是理念,“HTTP人類。”
您可以使用在您的計算機pip上安裝requests:
$ python -m pip install requests
讓我們探索如何requests通過使用它來訪問網站上的文本來提高可讀性。使用可信賴的瀏覽器處理此任務時,您應遵循以下步驟:
打開瀏覽器。
輸入網址。
看看網站的文字。
你怎么能用代碼實現同樣的結果?首先,您在偽代碼中列出了必要的步驟:
導入您需要的工具。
獲取網站數據。
打印網站的文本。
理清邏輯后,您可以使用requests庫將偽代碼轉換為 Python:
>>>
>>> import requests >>> response = requests.get("http://www.example.com") >>> response.text
代碼讀起來幾乎像英語,簡潔明了。雖然使用標準庫的urllib包來構建這個基本示例并不困難,但requests即使在更復雜的場景中也能保持其直接的、以人為中心的語法。
在下一個示例中,您將看到只需幾行 Python 代碼就可以實現很多目標。
requests?很強大
讓我們加強游戲并挑戰requests更復雜的任務:
登錄到您的 GitHub 帳戶。
保留該登錄信息以處理多個請求。
創建一個新的存儲庫。
創建一個包含一些內容的新文件。
僅當第一個請求成功時才運行第二個請求。
接受并完成挑戰!下面的代碼片段完成了上述所有任務。所有你需要做的就是代替兩個字符串?"YOUR_GITHUB_USERNAME",并"YOUR_GITHUB_TOKEN"與你的GitHub用戶名和令牌,分別為個人訪問。
注意:要創建個人訪問令牌,請單擊生成新令牌并選擇存儲庫范圍。復制生成的令牌并將其與您的用戶名一起使用以進行身份 驗證。
閱讀下面的代碼片段,將其復制并保存到您自己的 Python 腳本中,填寫您的憑據,然后運行它以查看requests操作:
import requests session = requests.Session() session.auth = ("YOUR_GITHUB_USERNAME", "YOUR_GITHUB_TOKEN") payload = { "name": "test-requests", "description": "Created with the requests library" } api_url ="https://api.github.com/user/repos" response_1 = session.post(api_url, json=payload) if response_1: data = { "message": "Add README via API", # The 'content' needs to be a base64 encoded string # Python's standard library can help with that # You can uncover the secret of this garbled string # by uploading it to GitHub with this script :) "content": "UmVxdWVzdHMgaXMgYXdlc29tZSE=" } repo_url = response_1.json()["url"] readme_url = f"{repo_url}/contents/README.md" response_2 = session.put(readme_url, json=data) else: print(response_1.status_code, response_1.json()) html_url = response_2.json()["content"]["html_url"] print(f"See your repo live at: {html_url}") session.close()
運行代碼后,繼續導航到它在最后打印出來的鏈接。您將看到在您的 GitHub 帳戶上創建了一個新存儲庫。新存儲庫包含一個README.md文件,其中包含一些文本,所有文本均使用此腳本生成。
注意:您可能已經注意到,該代碼僅進行一次身份驗證,但仍然能夠發送多個請求。這是可能的,因為該requests.Session對象允許您在多個請求中保留信息。
如您所見,上面的簡短代碼片段完成了很多工作,并且仍然可以理解。
為什么requests很棒
Python 的request庫是 Python 使用最廣泛的外部庫之一,因為它是一種可讀、可訪問且功能強大的與 Web 交互的工具。要了解有關使用 的多種可能性的更多信息requests,請查看使用 Python 進行 HTTP 請求。
parse?用于匹配字符串
我喜歡正則表達式的力量。使用正則表達式或regex,您幾乎可以搜索給定字符串中的任何模式。然而,強大的力量伴隨著巨大的復雜性!構建一個正則表達式可能需要大量的反復試驗,理解給定正則表達式的微妙之處可能更難。
parse是一個庫,它包含了正則表達式的大部分功能,但使用的語法更清晰,可能更熟悉。簡而言之,parse就是反向的f-strings。您可以使用與格式化字符串基本相同的表達式來搜索和解析字符串。讓我們來看看它在實踐中是如何工作的!
查找匹配給定模式的字符串
您需要一些要解析的文本。在這些示例中,我們將使用原始 f-strings 規范PEP 498。pepdocs是一個可以下載 Python Enhancement Proposal (PEP) 文檔文本的小實用程序。
安裝parse和pepdocs從PyPI:
$ python -m pip install parse pepdocs
首先,下載 PEP 498:
>>>
>>> import pepdocs >>> pep498 = pepdocs.get(498)
>>>
>>> import parse >>> parse.search("Author: {}\n", pep498)
parse.search()搜索的模式,在這種情況下"Author: {}\n",在任何地方給定的字符串中。您還可以使用parse.parse(), 將模式與完整字符串匹配。與 f 字符串類似,您可以使用花括號 (?{}) 來指示要解析的變量。
>>>
>>> parse.search("Author: {name} <{email}>", pep498)
這將返回一個Result包含匹配信息的對象。您可以訪問與搜索的所有結果.fixed,.named和.spans。您還可以使用[]獲取單個值:
>>>
>>> result = parse.search("Author: {name} <{email}>", pep498) >>> result.named {'name': 'Eric V. Smith', 'email': 'eric@trueblade.com'} >>> result["name"] 'Eric V. Smith' >>> result.spans {'name': (95, 108), 'email': (110, 128)} >>> pep498[110:128] 'eric@trueblade.com'
.spans?為您提供與您的模式匹配的字符串中的索引。
使用格式說明符
您可以使用 找到模式的所有匹配項parse.findall()。嘗試查找 PEP 498 中提到的其他 PEP:
>>>
>>> [result["num"] for result in parse.findall("PEP {num}", pep498)] ['p', 'd', '2', '2', '3', 'i', '3', 'r', ..., 't', '4', 'i', '4', '4']
嗯,這看起來不是很有用。PEP 使用數字引用。因此,您可以使用格式語法來指定您正在尋找數字:
>>>
>>> [result["num"] for result in parse.findall("PEP {num:d}", pep498)] [215, 215, 3101, 3101, 461, 414, 461]
添加:d告訴parse你正在尋找一個整數。作為獎勵,結果甚至從字符串轉換為數字。除了:d,您還可以使用f-strings使用的大多數格式說明符。
您還可以使用特殊的兩字符規范解析日期:
>>>
>>> parse.search("Created: {created:tg}\n", pep498)
:tg查找寫為day/month/year 的日期。如果順序或格式不同,您可以使用:tiand:ta以及其他幾個選項。
訪問底層正則表達式
parse建立在 Python 的正則表達式庫之上,re.?每次進行搜索時,都會parse在后臺構建相應的正則表達式。如果您需要多次進行相同的搜索,那么您可以使用parse.compile.
以下示例打印出 PEP 498 中對其他文檔的引用的所有描述:
>>>
>>> references_pattern = parse.compile(".. [#] {reference}") >>> for line in pep498.splitlines(): ... if result := references_pattern.parse(line): ... print(result["reference"]) ... %-formatting str.format [ ... ] PEP 461 rejects bytes.format()
該循環使用Python 3.8 及更高版本中可用的walrus operator來根據提供的模板測試每一行。您可以查看編譯模式以了解潛伏在新發現的解析功能背后的正則表達式:
>>>
>>> references_pattern._expression '\\.\\. \\[#\\] (?P
原始parse模式".. [#] {reference}"更易于讀取和寫入。
為什么parse很棒
正則表達式顯然很有用。然而,已經編寫了厚厚的書籍來解釋正則表達式的微妙之處。parse是一個小型庫,提供正則表達式的大部分功能,但語法更友好。
如果你比較".. [#] {reference}"和"\\.\\. \\[#\\] (?P
dateutil?用于處理日期和時間
如果您曾經不得不隨著時間進行任何編程,那么您就會知道它可以將您束縛在哪些復雜的結中。首先,您必須處理時區,其中地球上的兩個不同點在任何給定時刻都有不同的時間。然后你有夏令時,一年兩次的事件,其中一個小時發生兩次或根本不發生,但僅限于某些國家/地區。
您還必須考慮閏年和閏秒,以使人類時鐘與地球繞太陽的公轉保持同步。您必須圍繞Y2K和Y2038錯誤進行編程。這份清單不勝枚舉。
注意:如果你想繼續深入這個兔子洞,那么我強烈推薦時間和時區的問題,這是精彩而搞笑的湯姆斯科特對時間難以處理的一些方式的視頻解釋。
幸運的是,Python 在標準庫中包含了一個非常有用的模塊,稱為datetime.?Pythondatetime是存儲和訪問有關日期和時間的信息的好方法。但是,datetime有一些地方的界面不太好。
作為回應,Python 很棒的社區開發了幾個不同的庫和 API,用于以合理的方式處理日期和時間。其中一些擴展了內置的datetime,一些是完整的替代品。我最喜歡的圖書館是dateutil.
要按照下面的示例進行操作,請dateutil像這樣安裝:
$ python -m pip install python-dateutil
現在您已經dateutil安裝完畢,接下來幾節中的示例將向您展示它的強大功能。您還將看到如何dateutil與datetime.
設置時區
dateutil有幾件事要做。首先,它在 Python 文檔中被推薦作為datetime處理時區和夏令時的補充:
>>>
>>> from dateutil import tz >>> from datetime import datetime >>> london_now = datetime.now(tz=tz.gettz("Europe/London")) >>> london_now.tzname() # 'BST' in summer and 'GMT' in winter 'BST'
但是dateutil可以做的不僅僅是提供一個具體的tzinfo實例。這真的很幸運,因為在Python 3.9 之后,Python 標準庫將擁有自己訪問IANA 數據庫的能力。
解析日期和時間字符串
dateutildatetime使用parser模塊將字符串解析為實例變得更加簡單:
>>>
>>> from dateutil import parser >>> parser.parse("Monday, May 4th at 8am") # May the 4th be with you! datetime.datetime(2020, 5, 4, 8, 0)
請注意,dateutil即使您沒有指定它,它也會自動推斷該日期的年份!您還可以控制如何時區進行解釋或使用添加parser或工作與ISO-8601格式的日期。這為您提供了比datetime.
計算時差
另一個出色的特性dateutil是它能夠用relativedelta模塊處理時間算術。您可以從一個datetime實例中添加或減去任意時間單位,或者找出兩個datetime實例之間的差異:
>>>
>>> from dateutil.relativedelta import relativedelta >>> from dateutil import parser >>> may_4th = parser.parse("Monday, May 4th at 8:00 AM") >>> may_4th + relativedelta(days=+1, years=+5, months=-2) datetime.datetime(2025, 3, 5, 8, 0) >>> release_day = parser.parse("May 25, 1977 at 8:00 AM") >>> relativedelta(may_4th, release_day) relativedelta(years=+42, months=+11, days=+9)
這比datetime.timedelta因為您可以指定大于一天的時間間隔(例如一個月或一年)更靈活和強大。
計算重復事件
最后但并非最不重要的是,dateutil有一個強大的模塊,rrule用于根據iCalendar RFC計算未來的日期。假設您想為 6 月份生成一個定期站立時間表,發生在星期一和星期五的上午 10:00:
>>>
>>> from dateutil import rrule >>> from dateutil import parser >>> list( ... rrule.rrule( ... rrule.WEEKLY, ... byweekday=(rrule.MO, rrule.FR), ... dtstart=parser.parse("June 1, 2020 at 10 AM"), ... until=parser.parse("June 30, 2020"), ... ) ... ) [datetime.datetime(2020, 6, 1, 10, 0), ..., datetime.datetime(2020, 6, 29, 10, 0)]
請注意,您不必知道開始日期或結束日期是星期一還是星期五 —dateutil為您計算出來。另一種使用方法rrule是查找特定日期的下一次出現時間。讓我們找出下一次閏日,即 2 月 29 日,會像 2020 年一樣發生在星期六:
>>>
>>> list( ... rrule.rrule( ... rrule.YEARLY, ... count=1, ... byweekday=rrule.SA, ... bymonthday=29, ... bymonth=2, ... ) ... ) [datetime.datetime(2048, 2, 29, 22, 5, 5)]
在一個周六的下一個閏日將在2048年發生的有一噸多的實例中dateutil的文檔,以及一套練習嘗試。
為什么dateutil很棒
您剛剛看到的四個功能dateutil可以讓您在處理時間時更輕松:
設置與對象兼容的時區的便捷方法datetime
一種將字符串解析為日期的有用方法
用于進行時間運算的強大界面
一種計算重復日期或未來日期的絕妙方法。
下次當您嘗試隨著時間的推移進行編程而變灰時,請dateutil試一試!
typer?用于命令行界面解析
Python 開發人員通常從使用sys模塊的命令行界面 (CLI) 解析開始。您可以閱讀sys.argv以獲取用戶提供給您的腳本的參數列表:
# command.py import sys if __name__ == "__main__": print(sys.argv)
腳本的名稱和用戶提供的任何參數最終作為字符串值在sys.argv:
$ python command.py one two three ["command.py", "one", "two", "three"] $ python command.py 1 2 3 ["command.py", "1", "2", "3"]
但是,當您向腳本添加功能時,您可能希望以更明智的方式解析腳本的參數。您可能需要管理幾種不同數據類型的參數,或者讓用戶更清楚哪些選項可用。
argparse?笨重
Python 的內置argparse模塊可幫助您創建命名參數,將用戶提供的值轉換為正確的數據類型,并自動為您的腳本創建幫助菜單。如果您以前沒有使用argparse過,請查看如何使用 argparse 在 Python 中構建命令行接口。
的一大優點argparse是您可以以更具聲明性的方式指定 CLI 的參數,從而減少了大量的過程和條件代碼。
考慮以下示例,該示例用于sys.argv以用戶指定的次數打印用戶提供的字符串,同時對邊緣情況的處理最少:
# string_echo_sys.py import sys USAGE = """ USAGE: python string_echo_sys.py
此代碼為用戶提供了一種查看有關使用該腳本的有用文檔的方法:
$ python string_echo_sys.py --help USAGE: python string_echo_sys.py
用戶可以提供一個字符串和一個可選的打印字符串的次數:
$ python string_echo_sys.py HELLO! --times 5 HELLO! HELLO! HELLO! HELLO! HELLO!
要使用 實現類似的接口argparse,您可以編寫如下內容:
# string_echo_argparse.py import argparse parser = argparse.ArgumentParser( description="Echo a string for as long as you like" ) parser.add_argument("string", help="The string to echo") parser.add_argument( "--times", help="The number of times to echo the string", type=int, default=1, ) if __name__ == "__main__": args = parser.parse_args() print("\n".join([args.string] * args.times))
該argparse代碼是更具描述性的,并且argparse還提供了充分的論證分析和--help解釋你如何使用腳本選項,全部免費。
雖然argparse比sys.argv直接處理有很大的改進,但它仍然迫使您對 CLI 解析進行很多思考。您通常會嘗試編寫一個腳本來做一些有用的事情,所以花在 CLI 解析上的精力是浪費!
為什么typer很棒
typer提供了幾個相同的功能,argparse但使用了非常不同的開發范式。無需編寫任何聲明性、過程性或條件邏輯來解析用戶輸入,而是typer利用類型提示來內省您的代碼并生成 CLI,這樣您就不必花費太多精力來考慮處理用戶輸入。
首先typer從 PyPI安裝:
$ python -m pip install typer
現在您已經typer可以隨意使用了,下面是您如何編寫一個腳本來實現與argparse示例類似的結果:
# string_echo_typer.py import typer def echo( string: str, times: int = typer.Option(1, help="The number of times to echo the string"), ): """Echo a string for as long as you like""" typer.echo("\n".join([string] * times)) if __name__ == "__main__": typer.run(echo)
這種方法使用更少的功能行,這些行主要集中在腳本的功能上。腳本多次回顯字符串這一事實更為明顯。
typer甚至為用戶提供了Tab為他們的 shell生成補全的能力,這樣他們就可以更快地使用腳本的 CLI。
您可以查看Comparing Python Command-Line Parsing Libraries – Argparse、Docopt 和 Click以查看其中的任何一個是否適合您,但我喜歡typer它的簡潔和強大。
結論:五個有用的 Python 包
Python 社區已經構建了很多很棒的包。在本教程中,您了解了幾個有用的包,它們是 Python 標準庫中常見包的替代或擴展。
在本教程中,您學習了:
為什么pudb可能會幫助您調試代碼
如何requests改進您與 Web 服務器的通信方式
如何使用parse來簡化您的字符串匹配
哪些功能dateutil可用于處理日期和時間
為什么應該使用typer解析命令行參數
Python 正則表達式
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。