Python 模組與 import 教學:從基礎到實務,搞懂檔案引用與套件化結構

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絕對 import
  • from ..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 仍然是業界標準作法,可以避免不必要的錯誤。