一.簡單說明
python是通過module組織代碼的,每一個module就是一個python文件,但是modules是通過package來組織的。我們平時在簡單測試的時候
一般就是幾個Python文件存放在同級的目錄下,但是當我們開始嘗試開發更為復雜的項目時,package這個概念的使用就有助於我們寫的一個
個modules。
二.python package
package的定義很簡單,在當前目錄下有__init__.py文件的目錄即為一個package。
這里也會分為兩種情況,一種是空的__init__.py文件,另外一種是包含代碼的__init__.py文件。
無論空與非空,這個目錄都會被認為是一個package。
三.package的初始化
一個package被導入,無論什么時候,init.py的代碼都只會執行一次。
注意:由於package被導入時,init.py中的可執行代碼會被執行,所以小心在package中放置你的代碼,比如把代碼盡可能封裝成函數或類。
3.1 init.py內部的導入順序
當嘗試導入某個包時,如下:
from package import something
import語句會首先檢查something是不是__init__.py的變量。然后檢查是不是subpackage,再檢查是不是module,最后拋出ImportError。
順序如下:
1.init.py文件內變量
2.是不是package內的subpackage
3.是不是package內module
舉例說明:
這里我們創建一個yuhaohao的package,目錄下有sulli1.py sulli2.py init.py文件
文件內容內下:
sulli1.py
#!/usr/bin/python3
def tl():
print("Hello, function 'tl' from module 'sulli1' calling")
sulli2.py
#!/usr/bin/python3
def ol():
print("Hello, function 'ol' from module 'sulli2' calling")
init.py文件內容為空。
[root@centos8 pipeline]# python3
Python 3.6.8 (default, May 21 2019, 23:51:36)
[GCC 8.2.1 20180905 (Red Hat 8.2.1-3)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import yuhaohao
>>> yuhaohao
<module 'yuhaohao' from '/root/pipeline/yuhaohao/__init__.py'>
>>> yuhaohao.sulli1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: module 'yuhaohao' has no attribute 'sulli1'
>>> yuhaohao.sulli2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: module 'yuhaohao' has no attribute 'sulli2'
可以看出yuhaohao的路徑被包含在python的sys.path的環境變量中。但是sulli1.py和sulli2.py並沒有被導入。
如果想要在import yuhaohao
后自動加載sulli1和sulli2模塊,這里可以在__init__.py文件中增加如下內容:
import sulli1
import sulli2
第二種方案就是手動導入,當想使用模塊sulli1中的tl()函數時,需要手動導入
>>> import yuhaohao.sulli1 as yu
>>> yu.tl()
下面是一個更復雜的例子,下載的URL為:https://www.python-course.eu/sound1.tar.bz2
解壓后,文件結構如下:
sound
|-- effects
| |-- echo.py
| |-- __init__.py
| |-- reverse.py
| `-- surround.py
|-- filters
| |-- equalizer.py
| |-- __init__.py
| |-- karaoke.py
| `-- vocoder.py
|-- formats
| |-- aiffread.py
| |-- aiffwrite.py
| |-- auread.py
| |-- auwrite.py
| |-- __init__.py
| |-- wavread.py
| `-- wavwrite.py
`-- __init__.py
這里直接使用import sound
來導入這個package時,我們可以導入package sound,但是sound的子package(effects,filters,formats)並不會被自動
導入,子package不會被自動導入的原因是因為在sound目錄下的__init__.py文件並沒有任何關於導入子package的代碼。
導入sound:
>>> import sound
sound package is getting imported!
>>> sound.effects
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: module 'sound' has no attribute 'effects'
如果你想使用子package的內容,但是在父package的__init__.py的文件內並沒有導入,你需要手動導入
>>> import sound.effects
effects package is getting imported!
>>> sound.effects
<module 'sound.effects' from '/root/pipeline/sound/effects/__init__.py'>
如果你希望python幫你自動導入sound.effects你可以往sound目錄下的__init__.py文件寫入
"""An empty sound package
This is the sound package, providing hardly anything!"""
import sound.effects
print("sound package is getting imported!")
當然了,除了使用絕對路徑你可以使用相對路徑來導入sound.effects
"""An empty sound package
This is the sound package, providing hardly anything!"""
from . import effects
print("sound package is getting imported!")
這跟linux的命令行比較像,.代表當前目錄,..代表上級目錄。所以你可以在sound.effects的__init__.py文件內寫入
from .. import formats
參考鏈接:https://www.jianshu.com/p/178c26789011