1. 為什麼要在 Python 中呼叫其他檔案?有什麼好處?
程式越大,分割程式碼就越重要
剛開始學習 Python 時,把所有程式寫在一個檔案裡也沒問題。但隨著程式越來越大,邏輯會變得複雜,在同一個檔案中管理就變得困難。
這時候,「把函式或類別分開寫在不同檔案,需要時再呼叫」的結構設計就很重要了。這麼做可以讓程式碼更容易閱讀,也大幅提升維護性和重複使用的可能性。
提升程式碼的可重複使用性
例如:格式化文字的函式、格式化日期的函式等等,這些處理常常會在不同的腳本中重複使用。如果先把這些函式整理到一個檔案中,那在其他腳本中只要用 import
就可以輕鬆使用。
# 在 utils.py 中定義
def format_date(date):
return date.strftime('%Y-%m-%d')
# 從 main.py 呼叫
from utils import format_date
像這樣就能重複使用一次寫好的程式碼,大大提升開發效率。
改善維護性與可讀性
如果所有程式都寫在同一個檔案裡,一旦發生錯誤,就很難找出問題在哪裡。而且對其他人來說,也比較難看懂整個邏輯。
如果能依功能把檔案分開管理,就可以像這樣:
- 「資料庫處理在這個檔案」
- 「使用者輸入驗證在這個檔案」
這樣可以清楚區分各部分的責任。
好處包括:
- 更快找到並修正 bug
- 多人協作時減少衝突
- 更容易做程式碼審查
正式專案中必備的技能
當你使用 Python 開發 Web 應用程式,或管理多個機器學習模型時,把功能分檔並整理結構是一個基本功。使用 Django、FastAPI 等框架時,也會預設你了解資料夾結構與 import 的概念。
因此,即使是初學者,也應該在早期就學會「從其他檔案呼叫函式或類別」的做法。
2. Python 中 import 的基本用法
什麼是 import?
在 Python 中,如果你想使用其他檔案(模組)裡的函式或類別,就需要用到 import
指令。
透過它,你可以像在同一個檔案裡一樣,直接使用別的檔案中定義的程式。
這個機制讓我們可以輕鬆載入 Python 的標準函式庫,或是自己寫的模組。
最基本的用法:載入同一資料夾內的檔案
最基本的 import
使用方式,就是載入同一個資料夾下的其他檔案。
比方說,假設有以下的資料夾結構:
project/
├── main.py
└── utils.py
如果你想從 main.py
使用 utils.py
中定義的函式,可以這樣寫:
# utils.py
def greet(name):
return f"こんにちは、{name}さん!"
# main.py
import utils
print(utils.greet("佐川"))
就像這樣,只要指定檔案名稱(不含 .py),就可以使用裡面的函式或變數。
呼叫時使用「模組名稱.函式名稱」的格式。
使用 from-import 只載入特定函式
如果你只想使用某一個特定的函式,可以用 from 模組名稱 import 函式名稱
的格式來引入。
# main.py
from utils import greet
print(greet("佐川"))
這樣寫可以省去 utils.greet()
,直接使用 greet()
,更簡潔。
如果要同時載入多個函式,也可以用逗號分隔:
from utils import greet, farewell
使用別名(alias)簡化 import
如果模組名稱太長,或想讓程式碼更簡潔,可以使用 as
為它指定別名(alias)。
import utils as ut
print(ut.greet("佐川"))
這樣可以讓程式更短,而且也能避免與其他模組名稱衝突。
注意 import 的位置
在 Python 中,一般建議把 import
寫在檔案最上方。
但如果某些函式庫只在特定情況下才會用到,也可以在函式內部寫。
def use_numpy_temporarily():
import numpy as np
return np.array([1, 2, 3])
不過從可讀性和維護性來看,最好還是把 import 集中寫在最前面。
3. 從子資料夾或其他資料夾呼叫 Python 檔案
Python 中,import 的方式會隨資料夾結構改變
當你的 Python 專案有多層資料夾時,有時候無法單純使用 import 就載入其他檔案。
這時就需要理解正確的路徑設定與用法。
這一章會透過實例,說明如何從子資料夾或其他資料夾中呼叫函式或類別。
從子資料夾中的檔案 import
假設有以下的資料夾結構:
project/
├── main.py
└── tools/
└── formatter.py
如果要從 main.py
呼叫 formatter.py
中的函式,基本寫法如下:
# tools/formatter.py
def shout(text):
return text.upper() + "!"
# main.py
from tools import formatter
print(formatter.shout("hello"))
如果你只想引入特定函式,也可以這樣寫:
from tools.formatter import shout
print(shout("hello"))
這種寫法就是「資料夾名稱.檔案名稱」的形式來指定子資料夾中的檔案。
有些情況下需要 __init__.py 才能當作套件使用
在舊版 Python(3.2 以下)或某些工具中,要讓資料夾被當成模組套件(package),就必須包含 __init__.py
檔案。
tools/
├── __init__.py
└── formatter.py
這個檔案可以是空的沒關係。雖然在 Python 3.3 以後不是強制的,但加上會比較保險。
從父資料夾或兄弟資料夾 import
如果要從不同資料夾呼叫檔案,請參考以下的例子:
project/
├── main.py
└── modules/
└── helper.py
Python 預設不會自動搜尋 modules/
資料夾,所以你需要採取一些對應方式。
方式①:使用 sys.path 增加搜尋路徑
# main.py
import sys
import os
sys.path.append(os.path.join(os.path.dirname(__file__), 'modules'))
import helper
print(helper.some_function())
透過這種方式,你可以手動將資料夾加入 Python 的模組搜尋路徑中。
特別適合在專案根目錄下執行腳本的情境。
方式②:注意 Python 的執行位置
Python 的 import 行為會受到目前執行的資料夾影響。
你是從 project/
執行 main.py
,還是從 modules/
執行,可能導致結果不同。
# 正確執行方式
cd project
python main.py
另外在使用 VSCode 等編輯器時,「執行檔案」按鈕的預設位置也會影響執行結果,需要特別注意。
注意:絕對路徑 vs 相對路徑
from modules.helper import func
是絕對 importfrom ..modules import helper
是相對 import
相對 import 雖然方便,但容易受到執行位置影響而出錯。
建議初學者與實務開發中,以「絕對 import」為主,會比較穩定可靠。
4. 相對 import 與 絕對 import 的差異與用法
Python 的 import 有兩種主要方式
在 Python 中要從其他檔案呼叫程式碼,主要有兩種方式:
- 絕對 import(absolute import)
- 相對 import(relative import)
雖然這兩種方法的目的相同,但寫法和適用情境不同,選對方式能避免很多錯誤。
什麼是 絕對 import?
絕對 import 是指從專案的根目錄開始,明確指定模組的路徑。這是最常見、也是大多數專案推薦的寫法。
from tools.formatter import shout
像這樣,「資料夾名稱.檔案名稱.函式名稱」的格式就是絕對 import。
優點:
- 清楚明確,易讀性高
- 不同執行環境下也能正常運作
- 其他開發者也能快速理解結構
缺點:
- 如果資料夾層級很深,寫起來會比較長
什麼是 相對 import?
相對 import 是指以當前檔案的位置為基準,來引入其他模組。這種寫法多用於套件(package)內部模組之間的呼叫。
from . import formatter # 當前資料夾
from ..tools import formatter # 上一層資料夾
.
表示目前所在的資料夾,..
表示上一層資料夾。
優點:
- 清楚表示模組間的相對關係
- 方便套件內部模組之間互相引用
缺點:
- 容易受到執行位置影響,發生錯誤
- 不適合直接從外部執行的腳本
- 在大型專案中會讓結構變得難懂
什麼情況該用哪一種?實務中的選擇建議
根據 Python 官方文件,建議如下:
- 如果模組是給外部使用的:使用 絕對 import
- 如果模組只在套件內部使用:可以使用 相對 import
對初學者來說,使用絕對 import 會更穩定,出錯率也比較低。
實際錯誤範例:相對 import 失敗?
# example.py(直接執行)
from .module import func # ValueError: attempted relative import beyond top-level package
這個錯誤代表相對 import 在直接執行腳本時會失敗,因為 Python 不會把單一檔案視為套件的一部分。
解決方法是用模組方式執行:
python -m package.module
總結:預設使用絕對 import,特殊情況用相對 import
- 預設使用絕對 import(結構清晰、穩定性高)
- 只有在套件內部模組需要互相呼叫時才使用相對 import
雖然相對 import 很方便,但因為容易受執行位置影響而出錯,所以建議慎用。選對方式,才能寫出更穩定且易於維護的程式。
5. 模組管理的最佳做法:進行套件化(Package 化)
當專案檔案變多時,進行「套件化」是好方法
在使用 Python 開發大型專案時,將程式碼依功能切分到多個檔案是非常重要的。
這時,「套件化(Package 化)」的概念就派上用場了。
所謂套件,就是將多個 Python 模組(.py 檔案)依功能歸類成一個資料夾。這樣不僅可讀性更高,也更容易維護與重複利用。
__init__.py 的角色是什麼?
要讓某個資料夾被 Python 視為套件,原則上必須在裡面放一個 __init__.py
檔案。
project/
└── tools/
├── __init__.py
└── formatter.py
__init__.py
是 Python 判斷「這是一個套件」的依據。
雖然內容可以是空的,但你也可以在裡面進行初始化設定,或指定要對外公開的函式:
# tools/__init__.py
from .formatter import shout
這樣使用者就可以直接這樣引用:
from tools import shout
一個套件化專案的範例結構
下面是實際專案的套件化結構範例:
my_project/
├── main.py
└── tools/
├── __init__.py
├── formatter.py
└── validator.py
在這種情況下,你可以從 main.py
呼叫 tools
底下的所有模組:
# main.py
from tools import formatter, validator
print(formatter.shout("Hello"))
print(validator.is_valid("12345"))
套件化的好處整理
優點 | 說明 |
---|---|
結構清晰、好管理 | 可以依功能分類,讓專案更有條理 |
避免命名衝突 | 不同模組有獨立空間,不容易重名 |
方便重複利用 | 整個套件可以在其他專案中直接使用 |
便於測試與自動化 | 可以針對每個模組個別測試 |
Python 3.3 以後 __init__.py 可以省略?
從 Python 3.3 起,即使沒有 __init__.py
,資料夾也能當作套件使用(稱為隱式套件)。
但實務上,以下幾個理由仍然建議加上:
- 某些工具或函式庫仍要求存在
- 如果需要初始化設定或指定公開函式,就一定要寫
- 開發者能一眼知道這是「套件」
因此,加上 __init__.py
仍然是業界標準作法,可以避免不必要的錯誤。
