Python 的 import 是怎麼運作的?
你好,我是 somenzz,可以叫我徵哥。
Python 的import 是非常直覺的,但即使這樣,有時你會發現,明明套件就在那裡,我們仍會遇到ModuleNotFoundError,明明相對路徑非常正確,就是報錯
ImportError: attempted relative import with no known parent package
導入同一個目錄的模組和不同的目錄的模組是完全不同的,本文透過分析使用import 經常遇到的一些問題,來幫助你輕鬆搞定import ,據此,你可以輕鬆創建屬於自己的包。
1.什麼是模組(module),什麼是套件(package)
模組(module)
#模組與套件的關係,可以類比檔案與目錄,模組就是文件。
Python 文件中這樣描述,一個 Python 檔案就是一個模組,Python 的檔案名稱(不帶後綴.py)就是模組名稱。
一個module 可以包含變數、函數和類,它們是該module 定義的命名空間的一部分,因此變數的命名問題不是問題,因為兩個不同的模組可以有同名的變數、函數和類。
套件(package)
模組與套件的關係,可以類比檔案與目錄,套件就是目錄。
package 裡面可以有 module,也可以有子套件(sub-package)。一個模組定義一個命名空間,以便變數、函數和類別可以在兩個不同的模組中具有相同的名稱,同樣的,一個包對其組成的包和模組做同樣的事情,可以透過點號存取主包中的模組和包。
一個基本的 package 可以包含 sub-package、modules、__init__.py(Python 3.3 之後非必要)、setup.py。一個可能的package 結構如下所示:
而setup.py 存在於你的package 所在的主目錄中,包含配置信息,如所需的依賴項、腳本和子包。你也可以指定有關 package 的元數據,例如 package 的名稱、作者、描述等。
setup.py 是 pip 用來安裝你的套件的檔案。
2.import 時發生了什麼
先舉一個簡單的例子,比如說同一個目錄有兩個文件,file1.py 和file2.py,內容很簡單,就列印各自的檔名,不同的是file2.py 裡面import 了file1:
#file1.py print("This is file1.py") #file2.py print("This is file2.py") import file1
運行file2.py 可以得到下面的結果:
❯ python file2.py This is file2.py This is file1.py
可以看出:
- import 很直觀,用誰就import 誰。
- import 語句就是一個普通的語句,可以放在任何位置。
- 一個檔案被 import 的時候,就會被執行,其內部的類別或物件將會加入其命名空間。
我們還要知道 import 的搜尋順序,只需要記住一點,那就是 import 會去 sys.path 裡面搜尋。
例如我在file2.py 的最後加上一行程式碼:import sys; print(sys.path) 就可以列印import 的搜尋路徑:
可以看出sys.path 的順序:
- 會先搜尋執行腳本所在的路徑
- 標準函式庫
- 第三方函式庫site-packages
關於sys.path 需要你注意的是:
- 在解釋器環境下,sys.path[0] 就是解釋器啟動時所在的路徑''
- sys.path 並不會依賴目前程式的工作路徑- os.getcwd(),只依賴第一個腳本所在的路徑:
- 如果一個模組導入另一個模組,而後者又導入另一個模組,則第一個模組的sys.path 是解釋器搜尋第二個導入語句的位置。
一旦模組或套件被找到,就會執行該模組或套件。如果套件裡面有初始化檔 __init__.py,導入的時候,會先執行 __init__.py。
然後要導入的項目就被加入到了其命名空間內,我們可以透過 xx.yy 的方式來使用。
3.何時用相對導入,什麼時候用絕對導入
先看看什麼是絕對導入,所謂絕對導入就是這樣的形式:
import aa import aa.bb from aa import bb
這樣的方式很直觀, import 會去sys.path 查找就行了,如果遇到了ModuleNotFoundError,思考一下為什麼sys.path 沒有我們要導入的包,或者手動把這個包的路徑插入到sys.path 中去。
再看看什麼是相對導入,所謂相對導入就是這樣的形式:
from . import aa from .aa import bb from .. import yy
也就是說相對路徑中有個. 號,用來表明要導入的模組或當前的包的相對位置。
舉個例子,我們 pythonimportexample 目錄下新建一個目錄 subpackage1,在 subpackage1 內新建兩個檔案 file3.py、file4.py。
內容如下:
file3.py :
print("This is file3.py")
file4.py:
#from . import file3 print("This is file4.py")
只要我们直接运行 file4.py,那是一定会报错的:
Python 提示我们:
ImportError: attempted relative import with no known parent package
也就是说相对导入不知道父包是谁,换句话说,这是一个子包,必须让父包来调用它,直接运行这个文件是不行的,即使你在 file4.py 的目录 subpackage1 同级的目录执行该文件也是不行的,见上图。
但是在 file4.py 的目录 subpackage1 同级的目录作为一个 module 来执行是可以的,如下图:
换句话说,我们把 subpackage1 作为一个包来让别人用,相对导入是可以的,比如说我们在目录 subpackage1 同级的目录新建一个 file5.py 的文件,内容如下:
file5.py:
from subpackage1 import file4。
然后,执行 python file5.py 可以看出,相对导入已经正常工作:
结论
- 如果是当做脚本文件直接运行的,使用绝对导入。
- 如果是当做模块供其他文件导入,使用相对导入。
4.一个自定义包的例子
先上一个图来看下目录及引用结构,方块的是目录,椭圆的是文件,曲线是引用:
其中 import_example 目录下有 setup.py 和 run.py
run.py 导入了 file4、file5、file6。
file4 导入了 file3,file5 导入了 file3。
file6 导入了 file2,file2 导入了 file1。
现在我们来执行一下 run.py 看下效果:
可以看出所有相对导入都已正常工作,虽然 file3 被导入了两次,但只执行了一次,说明 Python 内部已经考虑了同一个包的多重导入问题。
自定义包就是让其他文件导入使用的,因此 pythonimportexample目录下都使用相对导入,源代码见:
https://gitee.com/somenzz/code-example/tree/master/import_example
点阅读原文也可以直接访问。
这里还有一些自定义包的例子:
- dbinterface[1]
- transferfile[2]
最后的话
本文分享了什么是模块(module),什么是包(package),import 的搜索路径,也分享了相对导入和绝对导入的区别,最后举了一个非常实用的 import 例子,方便你构建自己的包。
以上是Python 的 import 是怎麼運作的?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

熱門話題

MySQL 有免費的社區版和收費的企業版。社區版可免費使用和修改,但支持有限,適合穩定性要求不高、技術能力強的應用。企業版提供全面商業支持,適合需要穩定可靠、高性能數據庫且願意為支持買單的應用。選擇版本時考慮的因素包括應用關鍵性、預算和技術技能。沒有完美的選項,只有最合適的方案,需根據具體情況謹慎選擇。

文章介紹了MySQL數據庫的上手操作。首先,需安裝MySQL客戶端,如MySQLWorkbench或命令行客戶端。 1.使用mysql-uroot-p命令連接服務器,並使用root賬戶密碼登錄;2.使用CREATEDATABASE創建數據庫,USE選擇數據庫;3.使用CREATETABLE創建表,定義字段及數據類型;4.使用INSERTINTO插入數據,SELECT查詢數據,UPDATE更新數據,DELETE刪除數據。熟練掌握這些步驟,並學習處理常見問題和優化數據庫性能,才能高效使用MySQL。

MySQL 可在無需網絡連接的情況下運行,進行基本的數據存儲和管理。但是,對於與其他系統交互、遠程訪問或使用高級功能(如復制和集群)的情況,則需要網絡連接。此外,安全措施(如防火牆)、性能優化(選擇合適的網絡連接)和數據備份對於連接到互聯網的 MySQL 數據庫至關重要。

MySQL數據庫性能優化指南在資源密集型應用中,MySQL數據庫扮演著至關重要的角色,負責管理海量事務。然而,隨著應用規模的擴大,數據庫性能瓶頸往往成為製約因素。本文將探討一系列行之有效的MySQL性能優化策略,確保您的應用在高負載下依然保持高效響應。我們將結合實際案例,深入講解索引、查詢優化、數據庫設計以及緩存等關鍵技術。 1.數據庫架構設計優化合理的數據庫架構是MySQL性能優化的基石。以下是一些核心原則:選擇合適的數據類型選擇最小的、符合需求的數據類型,既能節省存儲空間,又能提升數據處理速度

HadiDB:輕量級、高水平可擴展的Python數據庫HadiDB(hadidb)是一個用Python編寫的輕量級數據庫,具備高度水平的可擴展性。安裝HadiDB使用pip安裝:pipinstallhadidb用戶管理創建用戶:createuser()方法創建一個新用戶。 authentication()方法驗證用戶身份。 fromhadidb.operationimportuseruser_obj=user("admin","admin")user_obj.

直接通過 Navicat 查看 MongoDB 密碼是不可能的,因為它以哈希值形式存儲。取回丟失密碼的方法:1. 重置密碼;2. 檢查配置文件(可能包含哈希值);3. 檢查代碼(可能硬編碼密碼)。

MySQL Workbench 可以連接 MariaDB,前提是配置正確。首先選擇 "MariaDB" 作為連接器類型。在連接配置中,正確設置 HOST、PORT、USER、PASSWORD 和 DATABASE。測試連接時,檢查 MariaDB 服務是否啟動,用戶名和密碼是否正確,端口號是否正確,防火牆是否允許連接,以及數據庫是否存在。高級用法中,使用連接池技術優化性能。常見錯誤包括權限不足、網絡連接問題等,調試錯誤時仔細分析錯誤信息和使用調試工具。優化網絡配置可以提升性能

對於生產環境,通常需要一台服務器來運行 MySQL,原因包括性能、可靠性、安全性和可擴展性。服務器通常擁有更強大的硬件、冗餘配置和更嚴格的安全措施。對於小型、低負載應用,可在本地機器運行 MySQL,但需謹慎考慮資源消耗、安全風險和維護成本。如需更高的可靠性和安全性,應將 MySQL 部署到雲服務器或其他服務器上。選擇合適的服務器配置需要根據應用負載和數據量進行評估。
