網站首頁 編程語言 正文
package 在 python 中,是一種有效組織代碼,module 可以是一個文件,可以通過 import 來導入一個 module 單個文件,而 package 則是作為一個目錄來導入。隨后我們還會看一看多層嵌套是如何導入的。
>>> import collections,socket >>> print(collections.__path__) ['/anaconda3/envs/py38/lib/python3.8/collections'] >>> print(socket.__path__) Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: module 'socket' has no attribute '__path__'
我們看一看 python 提供標注庫,例如 collections 和 socket,這里 collections 是一個 package 也就是意味著其是一個目錄,在 python 文件,而 socket 則是一個 module,對于 socket 和我們之前介紹導入 module 一樣。package 與 module 不同就是具有?__path__
?屬性,我們可以通過?__path__
?來訪問到存放 python 文件的路徑。但是對于 module 并不存在這個屬性。
在 python 中,有兩種 package,分別是是 regular package 和 namespace package。
regular package:
我們首先來看一看 regular package,下面是一個 regular package 結構
main.py pkg1 ---__init__.py
在項目下,我們創建一個文件夾 kpg1 下面有一個文件?__init__.py
,這樣 package 就是 regular package,這樣這個文件夾的名稱就是一個 package 名稱,我們導入 package 就可以直接導入這個 package 名稱。在?__init__.py
?文件里添加如下語句.
print("importing pk1") def hi_say(): print("pkg1 say hi")
在 main.py 我們導入 package 也就是?import pkg1
,python 通過 finder 來定位到 package 位置,pathFinder 通過在 sys.path 中的 path 搜索來定位到 package 的位置。大家還記得嗎? sys.path 第一個 path 就是我們當前目錄,這是為什么 python 可以定位到 pkg1 ,就是根據,當我們導入 package python 就會自動執行 package 下面的?__init__.py
?文件。當你 import package 時,module 的編譯好 code 對象,我們可以通過?pkg1.hi_say()
?來。
print(pkg1.__path__)
通過 pkg1 的?__path__
?來方法 pkg1 的目錄絕對路徑。
print(pkg1.__file__)
而?__file__
?對應得到?__init__.py
?文件的絕對路徑。
print(pkg1.__package__)
也可以通過 package 的?__package__
?的屬性獲取 package 的名稱,同樣可以通過?__name__
?來獲取 module 的名稱。
接下來我們進一步加大難度,就是 pkg1 文件夾下再新建一個 mod1.py 文件
main.py pkg1 ---__init__.py ---mod1.py
__init__.py
?文件
print("importing pk1")
mod1.py 文件中,輸出一條"import mod1"的信息,還定義了 say_hi 函數,接下來我們想要做的事導入這個 module 然后執行其中 say_hi 方法。
print("importing mod1") def say_hi(): print("pkg1 say hi")
import sys import pkg1 print('pkg1' in globals())#True print('pkg1' in sys.modules)#True
我們導入 pkg1 這樣創建一個指向 module 對象的引用,然后添加全局變量中,同時作為 module 也會被添加到 sys.modules 緩存中。
然后當我們直接通過 pkg1.mod1 來訪問 mod1 module 會拋出下面錯誤,告訴用戶并不存在這個屬性
AttributeError: module 'pkg1' has no attribute 'mod1'
也就是只是簡單導入 package 并不會將其下的 module 一同導入,所以才會出現上面錯誤。如果想要導入 pkg1 下 mod1 我們需要使用?import pkg1.mod1
?這樣正確方式來導入 mod1
import sys import pkg1.mod1
大家注意一下當我們導入 mod1 正確方式是用 import pkg1.mod1,從下面輸出來看,python 先執行?__init__.py
?,也就是說 python 會先導入 package pkg1 然后再導入 module1 這樣順序。
importing pk1 importing mod1
如果下面方式可以訪問到 module mod1 中的 say_hi() 方法。
pkg1.mod1.say_hi()
print('pkg1' in sys.modules)#True print('pkg1.mod1' in sys.modules)#True print('pkg1' in globals())#True print('pkg1.mod1' in globals())#False
通過上面輸出我們發現 pkg1 和 pkg1.mod1 都存在于 sys.modules 緩存中,還有不難看出只有 pkg1 位于全局變量,我們只能通過 pkg1 的屬性來方法 mod1。
簡單總結一下,我們要方法一個 package 下的 module,首先會訪問這個 package 會執行 package 下的?__init__.py
?然后再去執行 module 代碼,在 sys.modules 保存 pkg1 和 pkg1.mod1 分別指向保存兩個 module 對象的內存地址。
原文鏈接:https://juejin.cn/post/7082334564676272142
相關推薦
- 2022-12-03 FFmpeg?Principle分析Out?put?File?數據結構_Android
- 2023-03-04 通過column-count和break-inside的CSS3屬性實現瀑布流
- 2022-02-22 記一個nginx錯誤directory index of “/var/www/xxxx/“ is f
- 2022-04-30 Python代碼顯得Pythonic(區別于其他語言的寫法)_python
- 2023-02-28 ts之定義對象高級使用 Record
- 2022-04-15 React+Node實現大文件分片上傳、斷點續傳秒傳思路_React
- 2022-03-30 一篇文章帶你了解C語言的選擇結構_C 語言
- 2022-03-28 go實現一個分布式限流器的方法步驟_Golang
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支