淺析Python中的絕對導(dǎo)入與相對導(dǎo)入
如果您從事的Python項目有多個文件,那么您以前可能不得不使用import語句。即使對于擁有多個項目的Python重度使用者(比如我),import也可能會造成混淆!您可能正在閱讀本文,因?yàn)槟雽ython中的import(尤其是絕對導(dǎo)入和相對導(dǎo)入)有更深入的了解。
1 Imports快速介紹
Python模塊是具有.py擴(kuò)展名的文件,而Python包是其中具有模塊的任何文件夾(或者在Python 2中是包含__init__.py文件的文件夾)。當(dāng)一個模塊中的代碼需要訪問另一模塊或程序包中的代碼時,你需要導(dǎo)入它。
但是如何一個模塊,假設(shè)您像這樣導(dǎo)入os模塊:
import os
Python要做的第一件事是在 sys.modules中查找名為os系統(tǒng)模塊. 這是以前導(dǎo)入的所有模塊的緩存。sys模塊提供了一系列關(guān)于Python運(yùn)行環(huán)境的變量和函數(shù)。如果在模塊緩存中找不到該名稱,Python將繼續(xù)搜索內(nèi)置模塊的列表。這些模塊與Python一起預(yù)裝,可以在Python標(biāo)準(zhǔn)庫中找到。如果在內(nèi)置模塊中仍然找不到該名稱,Python就會在sys.path定義的目錄列表中搜索它。該列表通常包括當(dāng)前目錄,首先搜索該目錄。
總結(jié)來說,Python尋找一個模塊主要有以下三個步驟:
1 通過sys.modules從已經(jīng)加載的模塊中尋找
2 從Python標(biāo)準(zhǔn)庫中尋找,Python標(biāo)注庫就是那些通過pip install安裝來的模塊
3 通過sys.path包含的目錄列表尋找,sys.path通常會自動導(dǎo)入當(dāng)前目錄,當(dāng)然sys.path也可以添加自己指定的路徑
當(dāng)Python找到該模塊時,它將其綁定到本地范圍內(nèi)的一個名稱。這意味著現(xiàn)在已經(jīng)定義了os,并且可以在當(dāng)前文件中使用os,而不會拋出ModuleNotFoundError。如果沒找到模塊就拋出ModuleNotFoundError,如下所示:
import os
但是要注意的另外一個問題是,導(dǎo)入模塊,會出現(xiàn)安全問題。請注意,Python的導(dǎo)入系統(tǒng)存在一些重大的安全風(fēng)險。這主要是由于其靈活性。例如,模塊緩存是可寫的,并且可以使用導(dǎo)入系統(tǒng)覆蓋Python的核心功能。從第三方程序包導(dǎo)入還會使您的應(yīng)用程序面臨安全威脅。
2 import語句的語法
現(xiàn)在您知道了導(dǎo)入語句的工作原理,讓我們探究它們的語法。您可以導(dǎo)入軟件包和模塊。(請注意,導(dǎo)入軟件包實(shí)際上是將軟件包的__init__.py文件作為模塊導(dǎo)入。)您還可以從軟件包或模塊中導(dǎo)入特定的對象。
通常有兩種類型的導(dǎo)入語法。直接使用模塊時,可以直接導(dǎo)入模塊,如下所示:
2.1 基本使用
import os
os可以是包或模塊。當(dāng)您使用第二種語法時,您將從另一個包或模塊中導(dǎo)入。下面是是一個實(shí)例
from os import path
path可以是模塊,子包或?qū)ο?,例如類或函?shù)。您還可以選擇重命名導(dǎo)入的資源,如下所示:
import os as so
這將把導(dǎo)入的os重命名為so。現(xiàn)在必須將其引用為so,否則將無法識別它。
2.2 導(dǎo)入聲明的樣式
PEP 8 是Python的官方樣式指南,在編寫導(dǎo)入語句時有一些提示。PEP 8詳細(xì)見https://pep8.org/#imports。
總結(jié)如下:
- 導(dǎo)入應(yīng)始終寫在文件頂部,在任何模塊注釋和文檔字符串之后。
- import應(yīng)該根據(jù)用途分為以下三類:
- 標(biāo)準(zhǔn)庫導(dǎo)入(Python的內(nèi)置模塊)
- 相關(guān)的第三方導(dǎo)入(已安裝但不屬于當(dāng)前應(yīng)用程序的模塊)
- 本地應(yīng)用程序?qū)耄▽儆诋?dāng)前應(yīng)用程序的模塊)
- 每個import都要用空格分隔
在每個導(dǎo)入組中按字母順序排列導(dǎo)入也是一個好主意。這使得查找特定導(dǎo)入變得更加容易,特別是當(dāng)一個文件中有許多導(dǎo)入時。以下是如何設(shè)置導(dǎo)入語句樣式的示例。以下的import語句分為三個不同的組,用空格隔開。在每個組中,它們也按字母順序排列。
''' 格式化的import如下所示 ''' # 標(biāo)準(zhǔn)庫 import datetime import os # 第三方庫 from flask import Flask # 本地庫 # import local_module
3 絕對import和相對import
3.1 絕對import
您已經(jīng)掌握了如何編寫import語句以及如何像專業(yè)人士那樣設(shè)計它們的樣式?,F(xiàn)在是時候?qū)W習(xí)一點(diǎn)關(guān)于絕對導(dǎo)入的知識了。絕對導(dǎo)入指定要導(dǎo)入的資源使用其從項目根文件夾中的完整路徑。
假設(shè)您具有以下目錄結(jié)構(gòu):
└── project
├── package1
│ ├── module1.py
│ └── module2.py
└── package2
├── __init__.py
├── module3.py
├── module4.py
└── subpackage1
└── module5.py
當(dāng)前目錄project其中包含兩個子目錄package1和package2。該package1目錄有兩個文件,module1.py和module2.py。
該package2目錄包含三個文件:兩個模塊module3.py和module4.py,以及一個初始化文件__init__.py。它還包含一個目錄,subpackage該目錄又包含一個文件module5.py。
讓我們假設(shè)以下內(nèi)容:
- package1/module2.py包含一個函數(shù)function1。
- package2/__init__.py包含一個類class1。
- package2/subpackage1/module5.py包含一個函數(shù)function2。
以下是絕對導(dǎo)入的實(shí)際示例:
from package1 import module1 from package1.module2 import function1 from package2 import class1 from package2.subpackage1.module5 import function2
module2中的內(nèi)容如下:
def function1(): passs
package2中__init__.py中的內(nèi)容如下:
class class1(): def __init__(): return
package2.subpackage1.module5中的內(nèi)容如下:
def function2(): pass
請注意,必須為每個包或文件提供來自頂級包文件夾的詳細(xì)路徑。這有點(diǎn)類似于它的文件路徑,但是我們使用點(diǎn)(.)而不是斜杠(/)。
對導(dǎo)入是首選,因?yàn)樗鼈兎浅G宄椭苯?。僅通過查看語句,就可以很容易地準(zhǔn)確知道導(dǎo)入的資源在哪里。此外,即使import語句的當(dāng)前位置發(fā)生更改,絕對導(dǎo)入仍然有效。實(shí)際上,PEP 8明確建議絕對導(dǎo)入。
但是,有時絕對導(dǎo)入可能會變得非常冗長,具體取決于目錄結(jié)構(gòu)的復(fù)雜性。想象一下這樣的聲明:
from package1.subpackage2.subpackage3.subpackage4.module5 import function6
太荒謬了吧?幸運(yùn)的是,在這種情況下,相對導(dǎo)入是一個不錯的選擇!
3.2 相對導(dǎo)入
相對導(dǎo)入指定相對于當(dāng)前位置(即import語句所在的位置)要導(dǎo)入的資源。有兩種類型的相對導(dǎo)入:隱式和顯式。隱式相對導(dǎo)入在Python3中已被棄用,因此我將不在這里介紹它們。
相對導(dǎo)入的語法取決于當(dāng)前位置以及要導(dǎo)入的模塊,包或?qū)ο蟮奈恢?。以下是相對?dǎo)入的一些示例:
from .some_module import some_class from ..some_package import some_function from . import some_class
您可以看到在上面的每個import語句中至少有一個點(diǎn)。相對導(dǎo)入使用點(diǎn)表示法來指定位置。
單點(diǎn)表示所引用的模塊或軟件包與當(dāng)前位置位于同一目錄中。兩個點(diǎn)表示它位于當(dāng)前位置的父目錄中,即上面的目錄中。三個點(diǎn)表示它位于祖父母目錄中,依此類推。如果您使用類似Unix的操作系統(tǒng),這可能對您來說很熟悉!
假設(shè)您具有與以前相同的目錄結(jié)構(gòu):
└── project
├── package1
│ ├── module1.py
│ └── module2.py
└── package2
├── __init__.py
├── module3.py
├── module4.py
└── subpackage1
└── module5.py
您可以function1通過package1/module1.py以下方式導(dǎo)入文件:
# package1/module1.py from .module2 import function1
你可以將class1和function2導(dǎo)入到package2/module3.py文件中:
# package2/module3.py from . import class1 from .subpackage1.module5 import function2
在第一個import語句中,單點(diǎn)表示您正在class1從當(dāng)前包中導(dǎo)入。請記住,導(dǎo)入軟件包實(shí)際上會將軟件包的__init__.py文件導(dǎo)入為模塊。
在第二個import語句中,您將再次使用一個點(diǎn),因?yàn)閟ubpackage1它與當(dāng)前模塊位于同一目錄中module3.py。
當(dāng)然這種方法有個極大問題,可能會報錯,如下所示:
ModuleNotFoundError: No module named '__main__.module2'; '__main__' is not a package
這是相對導(dǎo)入只有在父模塊已經(jīng)在當(dāng)前運(yùn)行環(huán)境中被導(dǎo)入過才有用,所以盡可能用絕對導(dǎo)入。解決辦法見:
相對導(dǎo)入的利與弊
相對導(dǎo)入的一個明顯優(yōu)勢是它們非常簡潔。根據(jù)當(dāng)前位置,他們可以將您之前看到的可笑的冗長的import語句變成如下所示的簡單內(nèi)容:
from …subpackage4.module5 import function6
不幸的是,相對導(dǎo)入可能會很混亂,尤其是對于目錄結(jié)構(gòu)可能會更改的共享項目。相對導(dǎo)入也不如絕對導(dǎo)入更易讀,而且很難說出導(dǎo)入資源的位置。
以上就是淺析Python中的絕對導(dǎo)入與相對導(dǎo)入的詳細(xì)內(nèi)容,更多關(guān)于Python絕對導(dǎo)入與相對導(dǎo)入的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
解決Vscode中jupyter出現(xiàn)kernel dead問題
遇到VSCode中Jupyter Kernel Dead時,可通過Anaconda Prompt安裝ipykernel解決,首先使用jupyter kernelspec list命令查看內(nèi)核,若發(fā)現(xiàn)缺少ipykernel,激活相應(yīng)虛擬環(huán)境,使用conda install ipykernel命令安裝,操作后,VSCode中Jupyter應(yīng)能正常運(yùn)行2024-09-09解決pymongo連接數(shù)據(jù)庫報錯certificate verify failed:certific
這篇文章主要介紹了解決pymongo連接數(shù)據(jù)庫報錯certificate verify failed:certificate has expired問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-01-01使用Python實(shí)現(xiàn)正態(tài)分布、正態(tài)分布采樣
今天小編就為大家分享一篇使用Python實(shí)現(xiàn)正態(tài)分布、正態(tài)分布采樣,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-11-11Python編寫一個驗(yàn)證碼圖片數(shù)據(jù)標(biāo)注GUI程序附源碼
這篇文章主要介紹了Python編寫一個驗(yàn)證碼圖片數(shù)據(jù)標(biāo)注GUI程序,本文給大家附上小編精心整理的源碼,需要的朋友可以參考下2019-12-12python smtplib模塊自動收發(fā)郵件功能(一)
這篇文章主要為大家詳細(xì)介紹了python smtplib模塊自動收發(fā)郵件功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-05-05