python pip-什么是pip?Python新手入门指南
什么是 pip ?pip 是 Python 中的標(biāo)準(zhǔn)庫管理器。它允許你安裝和管理不屬于 Python標(biāo)準(zhǔn)庫 的其它軟件包。本教程就是為 Python 新手介紹 pip。
通過本教程,你將學(xué)到:
1. 安裝 Python 的標(biāo)準(zhǔn)發(fā)行版中未包含的其他軟件包
2. 查找發(fā)布于 Python 包索引(PyPI)的包
3. 管理腳本和應(yīng)用程序的安裝需求
4. 卸載包及它的相關(guān)依賴
如你所見,Python 社區(qū)非常活躍,并且為 pip 創(chuàng)建了一些簡潔的替代方案,你可以在本教程稍后的部分看到。
pip 入門
那么,什么是 pip 呢?pip 是 Python 的包管理器。這意味著它是一個(gè)工具,允許你安裝和管理不屬于標(biāo)準(zhǔn)庫的其他庫和依賴。
軟件包管理極其重要,所以自 Python3 的 3.4 版本以及 Python2 的 2.7.9 版本開始,pip 一直被直接包括在 Python 的安裝包內(nèi),同樣還被用于 Python 的其它項(xiàng)目中,這使得 pip 成為了每一個(gè) Pythonista(Python用戶)必備的工具。
如果你已經(jīng)了解了其他語言,那么可能會對包管理器的概念比較熟悉。JavaScript 使用 npm 管理軟件包,Ruby 使用 gem,以及 .NET 使用 NuGet。Python 中,則是 pip 作為標(biāo)準(zhǔn)包管理器。
Python 的安裝器中自帶了 pip,所以你可以直接使用它,除非你安裝的是更早版本的 Python。你可以通過在控制臺中運(yùn)行以下命令來驗(yàn)證 pip 是否可用:
什么是pip?Python新手入門指南
你應(yīng)該可以看到一個(gè)類似的輸出,顯示 pip 的版本以及安裝位置還有 Python 的版本。如果你使用的是不包含 pip 的舊版本 Python,你可以根據(jù) pip 安裝文檔中相應(yīng)系統(tǒng)的說明進(jìn)行安裝。
你可能希望在虛擬環(huán)境中使用本教程的示例,以避免將包安裝到 Python 的全局安裝環(huán)境中。你可以從 Python 虛擬環(huán)境:入門級了解虛擬環(huán)境相關(guān)的信息,這篇文章的”使用虛擬環(huán)境“一節(jié)介紹了創(chuàng)建虛擬環(huán)境的基礎(chǔ)知識。
使用 pip 安裝軟件包
Python 被認(rèn)為是一種"內(nèi)置電池"式的語言。這表示 Python 標(biāo)準(zhǔn)庫包含大量的軟件包和模塊,這些模塊有助于開發(fā)人員開發(fā)腳本和應(yīng)用。
與此同時(shí),Python 擁有一個(gè)活躍的社區(qū),它提供了一個(gè)更大的軟件包集合,以供你開發(fā)所需。這些軟件包發(fā)布在 Python Package Index,也被稱為 PyPI(發(fā)音 Pie Pea Eye)。PyPI 托管了大量包,包括開發(fā)框架,工具和庫。
其中很多軟件包通過為已有功能提供了友好地接口來簡化 Python 開發(fā)。例如,你可以寫一個(gè)腳本,僅使用 Python 標(biāo)準(zhǔn)庫中的功能分析網(wǎng)頁的內(nèi)容:
什么是pip?Python新手入門指南
腳本中,導(dǎo)入了 cgi 和 http.client,這兩個(gè)都是在 Python 的標(biāo)準(zhǔn)庫中。你創(chuàng)建了一個(gè) HTTPSConnection 對象并指定服務(wù)器,然后調(diào)用 .request() 和 .getresponse() 解析響應(yīng)信息。
從響應(yīng)信息中,我們解析到 Content-Type 頭信息并且使用 cgi 模塊提取頁面編碼的字符集。
cgi.parse_header() 返回一個(gè)包括主要值和字典作為參數(shù)的元組。例如,Content-Type 頭信息可能包含一個(gè)像 text/html; charset=ISO-8859-1 的值。
這個(gè)元組將字符串 text/html 作為第一個(gè)元素,第二個(gè)元素是 {'charset': 'ISO-8859-1'} 這樣形式的字典。因?yàn)槟阒恍枰P(guān)心 charset 參數(shù),可以使用下劃線忽略元組的開頭:_, params = cgi.parse_header(content_type)。
注意:Python 中下劃線的含義解釋了如何從元組解包值。
對頁面編碼后,你可以閱讀相應(yīng)信息并解碼到文本中。你可以在控制臺中運(yùn)行這個(gè)例子查看它是怎么工作的:
什么是pip?Python新手入門指南
對于一個(gè)用于解析網(wǎng)頁內(nèi)容的小腳本來說,這看起來做的工作有點(diǎn)多。幸運(yùn)的是,有一個(gè) Python 的包可以簡化 HTTP 請求并提供了一個(gè)友好地接口來實(shí)現(xiàn)你的期望。
基礎(chǔ)包安裝
PyPI 托管了一個(gè)非常流行的庫 requests 來完成 HTTP 請求。你可以通過它的官方文檔站點(diǎn)了解所有的相關(guān)信息。
第一步是在你的環(huán)境中安裝 requests 包。你可以運(yùn)行 pip help 來了解 pip 支持的命令:
什么是pip?Python新手入門指南
什么是pip?Python新手入門指南
如你所見,pip 提供了 install 命令來安裝軟件包。你可以運(yùn)行它來安裝 requests 包:
什么是pip?Python新手入門指南
你可以看到與上面類似的輸出信息。你可以使用 pip 以及 install 命令,其后跟著你想要安裝的包名。pip 會在 PyPI 中查找這個(gè)包,計(jì)算其依賴關(guān)系,安裝并確保 requests 正常工作。
你還可以看到當(dāng)前環(huán)境下 pip 的版本是 18.1,但是還有 19.0.1 版本可用。它還顯示了用于升級 pip 的命令,所以我們來試一下:
什么是pip?Python新手入門指南
注意這里,你使用了 python -m 來升級 pip。-m 開關(guān)告訴 Python 將模塊作為可執(zhí)行文件運(yùn)行。如果你要升級 pip,這么做是很有必要的,在安裝新的版本之前會卸載舊的版本,而當(dāng)工具在運(yùn)行時(shí)卸載它自己會導(dǎo)致錯(cuò)誤。
當(dāng)你將 pip 作為一個(gè)模塊運(yùn)行時(shí),Python 會將模塊加載到內(nèi)存中,并允許在這個(gè)模塊包運(yùn)行的時(shí)候刪除它。如果軟件包提供了頂層腳本 main.py,那么你可以像運(yùn)行腳本一下運(yùn)行這個(gè)軟件包。
你已經(jīng)安裝了 requests 并升級了 pip,現(xiàn)在可以使用 list 命令查看你的環(huán)境中安裝了哪些軟件包。
什么是pip?Python新手入門指南
如上所示,pip 已經(jīng)升級到了 19.0.1 版本(目前最新版本),并且安裝了 requests 2.21.0 版本。
命令 pip install 會查找并安裝軟件包的最新版本。同時(shí)還會搜索軟件包元數(shù)據(jù)中的依賴列表,并安裝這些依賴以確保軟件包滿足所有的需求。
這里你可以看到安裝了很多軟件。你可以使用 pip 中的 show 命令查看包的元數(shù)據(jù)信息:
[圖片上傳失敗...(image-90ab4f-1565242498214)]
元數(shù)據(jù)中列出了依賴項(xiàng) certifi,chardet,idna 和 urllib3,而且你可以看到這些都已經(jīng)安裝好了。
既然已經(jīng)安裝了 requests 包,我們可以修改上面的例子,來看看如何更方便地解析網(wǎng)頁的內(nèi)容:
什么是pip?Python新手入門指南
因?yàn)槟阋呀?jīng)在開發(fā)環(huán)境中安裝了 requests 包,可以像導(dǎo)入其他標(biāo)準(zhǔn)庫一樣導(dǎo)入它。
可以看到,requests.get() 處理了 HTTP 連接并返回一個(gè)與之前例子相似的響應(yīng),但是簡潔方便了很多。
因?yàn)?requests 已經(jīng)幫你處理了大部分情況,所以你不需要考慮頁面的編碼問題。而且,requests 還通過 requests.Response 對象提供了一個(gè)更加靈活的接口來處理特殊情況。
使用 requirements.txt 需求文件
pip install 命令只會安裝最新發(fā)布的軟件包版本,但是有時(shí)候,你可能希望根據(jù)代碼運(yùn)行情況安裝特定的版本。
你還希望在開發(fā)和測試時(shí)指定創(chuàng)建的依賴和版本,這樣就可以在生產(chǎn)環(huán)境避免應(yīng)用程序出現(xiàn)意外情況。
需求文件可以精確指定需要安裝的軟件包和版本。運(yùn)行 pip help 你可以看到一個(gè) freeze 命令,它會按照格式化輸出以已經(jīng)安裝的軟件包。你可以使用這個(gè)命令,將輸出重定向到文件以生成一個(gè)需求文件:
什么是pip?Python新手入門指南
freeze 命令將所有軟件包以及版本信息轉(zhuǎn)儲到標(biāo)準(zhǔn)輸出,所以你可以重定向這些輸出到文件中。這樣就可以在其他系統(tǒng)中根據(jù)這個(gè)需求文件執(zhí)行精準(zhǔn)安裝。約定這個(gè)需求文件名為 requirements.txt,但是你也可以根據(jù)個(gè)人喜好命名。
如果你希望在其他系統(tǒng)中復(fù)制你的開發(fā)環(huán)境,你可以運(yùn)行 pip install 命令并用 -r 開關(guān)指定需求文件:
什么是pip?Python新手入門指南
軟件包的版本會根據(jù) requirements.txt 所列出的進(jìn)行匹配:
什么是pip?Python新手入門指南
你可以將 requirements.txt 文件提交到資源控制器,這樣就可以使用它在其它機(jī)器上創(chuàng)建精準(zhǔn)匹配的環(huán)境了。
微調(diào)需求文件
軟件包及其依賴的版本可能會導(dǎo)致硬編碼問題,這是因?yàn)檐浖鼤槍?bug 以及安全修復(fù)進(jìn)行頻繁的更新,而你可能希望在它們發(fā)布后立即做出更改。
需求文件的格式允許你使用邏輯運(yùn)算符指定依賴的版本,這為確保更新包提供了更多的靈活性,但是仍然要定義一個(gè)包的基礎(chǔ)版本。
使用你常用的編輯器并作以下修改:
什么是pip?Python新手入門指南
你可以通過改變邏輯運(yùn)算符為 >= 來告知 pip 精準(zhǔn)安裝已發(fā)布的指定版本或更高版本。當(dāng)你使用 requirments.txt 設(shè)置了一個(gè)新的環(huán)境,pip 會查找滿足需求的最新版本并安裝。你可以使用帶有 --upgrade 開關(guān)的 install 命令來升級你需求文件中定義的軟件包:
什么是pip?Python新手入門指南
這里沒有任何升級操作,因?yàn)槟愕能浖际亲钚掳姹?#xff0c;但是如果在包列表中發(fā)布了新的版本,那么這個(gè)包就會被升級到最新版本。
理想情況下,新版本的包會向后兼容并且沒有新引入的 bug。不幸的是,新版本引入的更改還是可能會破壞你的應(yīng)用程序。需求文件的語法支持額外的版本說明符來微調(diào)你的需求。
比方說 requests 發(fā)布了新版本 3.0,但是有一些更改與你的應(yīng)用程序不兼容。你可以通過修改需求文件來禁止安裝 3.0 版本以及更高的版本:
什么是pip?Python新手入門指南
更改 requests 的版本操作符可以確保不會安裝 3.0 或更高的版本。pip 的文檔提供了全部的需求文件格式,你可以查閱以了解更多相關(guān)信息。
生產(chǎn)與開發(fā)環(huán)境的依賴關(guān)系
你在開發(fā)期間安裝的依賴并不都是你的應(yīng)用程序的依賴。其中有很多發(fā)布到 PyPI 上的包,是你開發(fā)過程中想用到的工具或庫。
比方說,你可能希望對你的應(yīng)用做單元測試,你需要單元測試的框架。一個(gè)流行的單元測試框架是 pytest。你希望在你的開發(fā)環(huán)境中安裝它,但是卻不希望在生產(chǎn)環(huán)境也安裝它,因?yàn)樗皇菓?yīng)用的依賴。
這時(shí)你會創(chuàng)建第二個(gè)需求文件(requirements_dev.txt)來列出配置開發(fā)環(huán)境需要的工具:
什么是pip?Python新手入門指南
這里需要你使用 pip 安裝兩個(gè)需求文件:requirements.txt 和 requirements_dev.txt。還好,pip 允許在需求文件內(nèi)部指定一些額外的參數(shù)。你可以需改 requirements_dev.txt 文件支持同時(shí)安裝生產(chǎn)文件 requirements.txt 中的需求:
什么是pip?Python新手入門指南
注意這里你使用了完全相同的 -r 開關(guān)來安裝生產(chǎn)文件 requirements.txt。需求文件格式允許你在需求文件中指定其他參數(shù)。
為生產(chǎn)環(huán)境凍結(jié)需求文件
你已經(jīng)創(chuàng)建了生產(chǎn)和開發(fā)環(huán)境的需求文件,并將它們添加到資源控制器中。這些文件可以靈活 的指定版本,可以通過發(fā)布的依賴進(jìn)行修復(fù) bug。你還可以測試你的應(yīng)用程序并為發(fā)布到生產(chǎn)環(huán)境做準(zhǔn)備。
因?yàn)橐呀?jīng)知道開發(fā)環(huán)境應(yīng)用程序的所有測試已經(jīng)正常通過,所以你可能希望確保生產(chǎn)環(huán)境的依賴版本與整合管道或構(gòu)建過程中使用的完全相同。
目前的版本說明符并不能保證會在生產(chǎn)環(huán)境部署完全相同的版本,所以你需要凍結(jié)說明文件 ,像之前看到的那樣。
你創(chuàng)建了一個(gè)干凈的生產(chǎn)環(huán)境,并使用 requirements.txt 文件安裝了生產(chǎn)需求。安裝完需求文件之后,你可以凍結(jié)當(dāng)前這個(gè)特定的版本,并將輸出轉(zhuǎn)儲到生產(chǎn)環(huán)境的 requirements_lock.txt 文件中。該 requirements_lock.txt 文件中包含精確的版本說明符,并且可以復(fù)制當(dāng)前環(huán)境。
搜索可用包
當(dāng)你擁有更多的 Python 經(jīng)驗(yàn)之后,會有一套熟悉的軟件包,并且可以用于大部分應(yīng)用程序。包 requesta 與 pytest 對于補(bǔ)充你的 Python 工具箱來說,都是很好的選擇。
有時(shí)你需要解決不同的問題,并想要找到一個(gè)可以幫助你解決問題的工具或庫。上面提到,命令 pip help 展示了一個(gè)命令 search,可以搜索在 PyPI 上發(fā)布包。
我們看看這個(gè)命令有什么用:
什么是pip?Python新手入門指南
什么是pip?Python新手入門指南
這個(gè)命令給出了一組選項(xiàng)以及一個(gè) 參數(shù)。query 是一個(gè)用于搜索的字符串,可以匹配包名及描述。
注意:你可以使用 pip help 檢索其它支持的命令的信息。
假設(shè)你的應(yīng)用需要訪問一個(gè)使用 OAuth2 授權(quán)的服務(wù)。理想情況下,會有一個(gè)庫使用 requests 執(zhí)行或者其它類似的接口實(shí)現(xiàn)。用 pip 到 PyPI 上搜索一下:
什么是pip?Python新手入門指南
search 命令選項(xiàng)生成了一個(gè)相當(dāng)大的包集合。其中一些看起來像 django-oauth 這樣指定了一個(gè)服務(wù)或技術(shù)。希望找到一個(gè)像是 requests-oauth 的信息。很不幸,除了簡短的描述,并沒有其它信息。
多數(shù)情況下,你希望直接在 PyPI 的網(wǎng)站搜索包。PyPI 為其索引提供了搜索功能,并通過包中公開的元數(shù)據(jù)(如框架,主題,開發(fā)狀態(tài)等)過濾搜索結(jié)果。
PyPI 中用同一個(gè)術(shù)語搜索可能會產(chǎn)生大量的結(jié)果,不過你可以對它們進(jìn)行分類過濾。比如,如果你想要找到可以幫助你開發(fā)應(yīng)用的庫,你可以展開 Intended Audience 并選擇 Developers。另外,你可能還需要一個(gè)穩(wěn)定且可用于生產(chǎn)的包,可以展開 Development Status 并選擇 Production/Stable。
什么是pip?Python新手入門指南
你可以應(yīng)用其他過濾器以及調(diào)整搜索詞,直到找到你想要的包。
搜索結(jié)果提供了一個(gè)包頁面的鏈接,包含了更多的信息以及想要的文檔。下面我們看看 requests-oauth2 的信息:
什么是pip?Python新手入門指南
這個(gè)項(xiàng)目頁面提供了更多的信息,而且看起來還有一個(gè)指向 Home 頁的鏈接。該鏈接指向 Github 上的項(xiàng)目倉庫。你可以看到項(xiàng)目相關(guān)的更多信息以及一些使用示例。
看到初始源代碼倉庫,像是找到了無價(jià)的財(cái)富。在那里,你可以通過查看最新的提交日志,PR(pull request)次數(shù)以及打開的 issues 等問題來找到一些項(xiàng)目的狀態(tài)和提示。
另外還有一個(gè)查找包的方式,Google。被廣泛使用的 Python 庫會展示在 google 搜索的頂部,并且你應(yīng)該能看到指向 PyPI 中包或者源代碼倉庫的鏈接。
找到一個(gè)合適包需要花費(fèi)一些時(shí)間研究,但是只要找到了,就可以為你的開發(fā)過程提速。
卸載包
有時(shí)候你不得不卸載一個(gè)軟件包。要么是你找到了一個(gè)更好的包來替代它,要么是確實(shí)不需要某些功能了。卸載軟件包會有一些棘手。
注意這里,當(dāng)你安裝了 requests,pip 同時(shí)也安裝了其他的依賴。你安裝的包越多,多個(gè)包擁有相同的依賴的可能性越大。這里 pip 的 show 命令就派上用場了。
卸載包之前,先確保你已經(jīng)對這個(gè)包運(yùn)行了 show 命令:
[圖片上傳失敗...(image-63734b-1565242498214)]
注意最后的兩個(gè)屬性 Requires 和 Required-by。show 命令向我們展示了 requests 需要依賴 urllib3,certifi,chardet 和 idna。你可能希望卸載其中的兩個(gè)。而且你可以看到 requests 沒有被其他包引用,所以它可以安全地卸載。
你應(yīng)該對 requests 中所有的依賴都運(yùn)行一下 show 命令,以確保沒有其他庫依賴它們。你了解了這些依賴次序之后,就可以使用 uninstall 命令來卸載它們。
什么是pip?Python新手入門指南
卸載包會顯示將要刪除的文件并要求確認(rèn)。如果你確認(rèn)要卸載這個(gè)包并且已經(jīng)檢查了它的依賴關(guān)系,知道沒有其他包在使用這個(gè)包,那么可以使用 -y 開關(guān)來隱藏文件列表和確認(rèn)提示信息:
什么是pip?Python新手入門指南
你可以一次調(diào)用指定所有你想卸載的包:
什么是pip?Python新手入門指南
你還可以通過提供 -r 選項(xiàng)來刪除需求文件中列出的全部軟件包。這個(gè)命令會對每一個(gè)包都提示確認(rèn)信息,如果你已經(jīng)明確知曉你的操作,可以通過 -y 開關(guān)禁止這些提示:
什么是pip?Python新手入門指南
在你想要卸載包時(shí),一直都要記得檢查一遍依賴項(xiàng)。你可能希望卸載一個(gè)軟件包的所有依賴,不過如果有其它軟件包在使用這些依賴,會導(dǎo)致程序崩潰。
pip 的替代品
pip 是所有 Pythonista 必備的基本工具,很多應(yīng)用程序和項(xiàng)目使用它作為軟件包管理器。本教程幫助你了解基礎(chǔ)知識,而 Python 社區(qū)非常積極的為其它開發(fā)人員提供了很棒的工具和庫。其中包括 pip 的替代品,期望實(shí)現(xiàn)簡單高效的包管理。
在本節(jié),你將了解到 Python 中其它可用的包管理工具。
萬能的 Conda
Conda 是一個(gè)包括 Python 在內(nèi)的多種語言的包、依賴及環(huán)境管理器。實(shí)際上,它最早來源于 Anaconda,作為 Python 中研究數(shù)據(jù)科學(xué)的包出現(xiàn)。
Conda 廣泛用于數(shù)據(jù)科學(xué)和機(jī)器學(xué)習(xí)應(yīng)用程序,并使用自己的索引來托管兼容的軟件包。
Conda 不僅可以管理包的依賴項(xiàng),還可以管理應(yīng)用的虛擬環(huán)境,安裝兼容并存的 Python 版本,為生產(chǎn)部署打包應(yīng)用。
在 Windows 系統(tǒng)上為機(jī)器學(xué)習(xí)設(shè)置 Python 很好的介紹了 Conda,它探討了包和環(huán)境管理。唯一與 Windows 相關(guān)的特定信息是安裝,因此如果你使用的是其他系統(tǒng)平臺,它仍然是可信的。
Pipenv
Pipenv 是另外一種包管理工具,旨在為 Python “提供全世界最好的包”。由于將虛擬環(huán)境與包管理合并到一個(gè)工具中,pipenv 在 Python 社區(qū)獲得了極大的關(guān)注。
它還解決了在使用 pip 手動管理依賴關(guān)系是遇到的一些常見問題,比如,包的版本,隔離開發(fā)與生產(chǎn)環(huán)境依賴,鎖定生產(chǎn)環(huán)境版本等。
Pipenv:新的 Python 打包工具指南是一份很好的學(xué)習(xí) Pipenv 及其包管理的入門材料。盡管這篇文章的標(biāo)簽是中級,但是作者對讀者做了很好的引導(dǎo),初學(xué) Python 的人也能理解這篇文章。
Poetry
Poetry 是另一個(gè)受到大量關(guān)注的 pip 替代品。與 Pipenv 類似,它簡化了包的版本管理并隔離了開發(fā)環(huán)境與生產(chǎn)環(huán)境的依賴,而且它將依賴隔離到一個(gè)虛擬環(huán)境中運(yùn)行。
如果你已經(jīng)了解 JavaScript 和 npm,會覺得 Poetry 非常熟悉。它不只是管理包,還可以幫助你為應(yīng)用和庫構(gòu)建發(fā)行版本并部署到 PyPI。如何向 PyPI 發(fā)布一個(gè)開源的 Python 包中一個(gè)很棒的 Poetry 介紹可以幫你入門。
總結(jié):什么是 pip?
本教程回答了問題:什么是 pip?你現(xiàn)在已經(jīng)知道,pip 是 Python 的包管理器,被很多項(xiàng)目用于依賴管理。現(xiàn)在 Python 安裝器已經(jīng)包含了 pip,使它成為所有的 Pythonista 都應(yīng)當(dāng)會用的基礎(chǔ)工具。
Python 提供了一個(gè)適用于開發(fā)各種應(yīng)用的標(biāo)準(zhǔn)庫擴(kuò)展,但是 Python 活躍的社區(qū)提供了更多的工具和庫,可以加速 Python 應(yīng)用開發(fā)。
這些工具和庫都發(fā)布在 Python 包索引(PyPI)上,并且使用 pip 允許開發(fā)者在自己的環(huán)境中安裝它們。
通過這篇教程,你可以學(xué)到:
1. 在命令行使用 pip 以及需求文件安裝新的軟件包
2. 管理依賴,隔離開發(fā)與生產(chǎn)環(huán)境,以及創(chuàng)建一個(gè)鎖定的需求文件
3. 通過 pip 和 PyPI 查找包
4. 在卸載包之前評估包依賴,以及如何卸載包此外,你已經(jīng)了解到保持依賴處于最新的重要性,而且,pip 的很多替代品可以幫你管理這些依賴。
如果你有任何問題,可以隨時(shí)在下面的評論部分留言,你還可以隨時(shí)在 pip 文檔頁面獲取更多信息。
英文原文:https://realpython.com/what-is-pip/譯者:敦偉
注:我這有個(gè)學(xué)習(xí)Python基地,里面有很多學(xué)習(xí)資料,感興趣的+Q群:895817687
總結(jié)
以上是生活随笔為你收集整理的python pip-什么是pip?Python新手入门指南的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 河南省“第三届金盾信安杯“部分WP
- 下一篇: typora如何导出深色背景的pdf