Python __init__ 檔
什麼是 __init__.py?
在 Python 中,__init__.py 是一個特殊檔案,其存在讓一個目錄被 Python 識別為 package(套件),而不只是普通資料夾。
作用
當你的目錄結構如下:
myproject/
├── __init__.py
└── utils.py
Python 便可以用 import myproject.utils 的方式載入模組。
若沒有 __init__.py,Python 3.3+ 雖支援 namespace packages(隱式套件),但仍建議明確加入此檔案以確保相容性與可讀性。
常見用途
- 空白檔案:僅標記目錄為 package
- 初始化邏輯:
import套件時自動執行的程式碼 - 公開 API:透過
__all__控制對外暴露的介面
# myproject/__init__.py
from .utils import helper_function
__all__ = ["helper_function"]
這樣使用者只需 from myproject import helper_function 即可取用。
具體應用場景
1. 簡化 import 路徑
不用讓使用者記住內部模組結構,透過 __init__.py 重新匯出,提供乾淨的公開介面。
# mylib/
# ├── __init__.py
# ├── _parser.py
# └── _validator.py
# mylib/__init__.py
from ._parser import parse
from ._validator import validate
使用者可以直接寫:
from mylib import parse, validate
# 而不是 from mylib._parser import parse
2. 套件版本管理
將版本號集中定義在 __init__.py,方便工具(如 setuptools)和使用者讀取。
# mylib/__init__.py
__version__ = "1.2.0"
__author__ = "Your Name"
其他地方讀取:
import mylib
print(mylib.__version__) # "1.2.0"
3. 自動註冊子模組(Plugin 系統)
框架常用此模式,讓子目錄的 plugin 在 import 時自動完成註冊。
# plugins/__init__.py
from . import csv_plugin, json_plugin, excel_plugin
只要 import plugins,三個 plugin 全部載入並完成初始化,不需逐一手動引入。
4. 環境初始化(logging、設定)
進入套件時統一設定 logging 格式或讀取環境變數,避免分散在各模組重複設定。
# myapp/__init__.py
import logging
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(message)s",
)
5. 條件式匯入(相容性處理)
根據執行環境決定載入哪個實作,常見於需要同時支援不同平台或依賴的套件。
# mylib/__init__.py
try:
from ._fast import compute # C extension 加速版
except ImportError:
from ._pure import compute # 純 Python 備援版
使用者直接 from mylib import compute,無需感知底層差異。
什麼時候不該用 __init__.py
1. __init__.py 塞太多邏輯
__init__.py 應該是「入口」,不是「倉庫」。若把大量業務邏輯、類別定義直接寫在裡面,會讓套件難以維護。
# 不建議:把所有東西塞進 __init__.py
class UserService:
...
class PaymentService:
...
def send_email():
...
應拆分到各自模組,再從 __init__.py 重新匯出。
2. 製造循環 import
__init__.py 在套件載入時最先執行,若它 import 了某模組,而該模組又 import 回套件本身,就會造成循環依賴錯誤。
# mylib/__init__.py
from .models import User # models.py 若又 import mylib,就會出錯
遇到此情況,應改為在函式內部做 lazy import,或重新整理模組依賴關係。
3. 大型 namespace package 不需要它
若你在維護一個跨多個發行套件共用同一頂層命名空間(如 mycompany.billing、mycompany.auth 分屬不同 repo),刻意不放 __init__.py 才能讓 Python 的 namespace package 機制正確合併它們。
加了反而會破壞其他套件對同一命名空間的存取。
4. 單一檔案就夠用時
若你的程式碼只有一個 utils.py,直接 import utils 即可,完全不需要建立資料夾 + __init__.py 的結構。過早建立套件結構只會增加複雜度。