Python 套件的建立・管理・發佈指南|從入門到實戰的完整解析

目次

1. 前言

Python 套件的重要性

Python 的套件是一種將多個模組組合在一起的結構,能夠讓程式碼的重複利用與管理變得更加簡單。特別是在大型專案中,透過適當地設計套件架構,可以大幅提升程式碼的可讀性與維護性。

雖然 Python 生態系統中已經有許多實用的套件(函式庫)可供使用,但透過自行開發套件並應用於專案中,將能讓開發過程更加靈活。

本文的目的與概要

本篇文章將針對 Python 套件進行詳細說明,內容包括以下幾點:

  • 套件的基本概念與結構
  • 如何建立自製套件
  • 如何匯入套件
  • 使用 pip 進行套件管理
  • 將套件發佈至 PyPI(Python Package Index)的流程
  • 常見錯誤與對應解法(FAQ)

閱讀本指南後,您將能系統性地理解 Python 套件的運作方式,並實際應用在開發中。

適合的讀者對象

本篇文章適合以下讀者:

  • 已具備 Python 基礎語法知識,並曾撰寫簡單腳本或函式者
  • 希望整理專案架構、撰寫易於重複利用程式碼的開發者
  • 想要建立自己的套件並發佈到 PyPI 的人

本指南旨在協助這些讀者更加深入理解 Python 套件,並提供實用的開發知識。

2. 什麼是 Python 套件?

套件與模組的差異

在 Python 中,為了讓程式碼結構更清晰、便於重複使用,引入了「模組」與「套件」的概念。

  • 模組(Module)
    指的是單一的 Python 腳本(.py 檔案)。例如,以下的 Python 檔案就是一個模組:
  # sample_module.py
  def greet():
      return "Hello, Python!"
  • 套件(Package)
    是由多個模組組成的資料夾(目錄),通常會包含一個 __init__.py 檔案。透過套件可以更有組織地管理多個模組。
  mypackage/
  ├── __init__.py
  ├── module1.py
  ├── module2.py

與函式庫的差異

「函式庫(Library)」這個詞也經常被使用,它是比模組或套件更廣泛的概念。
函式庫通常是由多個套件所組成,用來提供特定功能的工具集合。

術語說明
模組單一的 Python 腳本檔(.py 檔案)
套件包含多個模組的目錄結構
函式庫由多個套件所組成的軟體集合

例如,requestsnumpy 是套件,而 SciPyDjango 則是結合多個套件的函式庫。

__init__.py 的角色

在套件目錄中,__init__.py 是一個特殊的檔案,它的存在讓 Python 能夠將該資料夾視為套件。

__init__.py 的基本用法

雖然 __init__.py 可以是空的,但你也可以在裡面定義一些初始化設定或匯出套件中的主要函式,例如:

# mypackage/__init__.py
from .module1 import greet

def welcome():
    return "Welcome to mypackage!"

透過上述設定,當從外部匯入 mypackage 套件時,就能直接使用 greet() 函式:

from mypackage import greet
print(greet())  # Hello, Python!

命名空間套件(Namespace Package)

從 Python 3.3 開始,即使沒有 __init__.py,Python 也能辨識為套件,這種形式被稱為「命名空間套件(Namespace Package)」。不過,為了相容性與可讀性,大多數情況下仍建議保留 __init__.py

小結

  • 模組 是單一 .py 檔案,而套件 是由多個模組組成的資料夾結構。
  • 函式庫 是包含多個套件與模組的軟體集合。
  • __init__.py 是辨識套件的重要檔案,也可以用來定義初始化內容與匯出功能。
  • 從 Python 3.3 起可使用「命名空間套件」,但一般仍建議保留 __init__.py
RUNTEQ(ランテック)|超実戦型エンジニア育成スクール

3. 如何建立 Python 套件

基本的套件目錄結構

Python 套件需要遵循一定的目錄結構才能正常運作。以下是一個簡單的套件目錄範例:

mypackage/
├── __init__.py  # 套件識別檔案
├── module1.py   # 模組1
├── module2.py   # 模組2
└── subpackage/  # 子套件
    ├── __init__.py
    ├── submodule1.py
    └── submodule2.py

各個檔案的角色

  • mypackage/:套件的根目錄
  • __init__.py:標示此資料夾為 Python 套件(Python 3.3 之後可以省略,但建議保留)
  • module1.pymodule2.py:套件中的模組檔案
  • subpackage/:子套件,內含其他模組

__init__.py 的建立與功能

__init__.py 檔案的作用是讓 Python 能夠識別該目錄為套件,並可以定義在匯入時執行的初始化邏輯。

簡單的 __init__.py

即使是空的 __init__.py 檔案,也能讓資料夾作為套件運作:

# mypackage/__init__.py

__init__.py 中加入初始化設定

以下是一個更實用的範例,示範如何在 __init__.py 中定義初始化邏輯與匯出功能:

# mypackage/__init__.py
from .module1 import greet

def welcome():
    return "Welcome to mypackage!"

這樣設定後,在匯入套件時就能直接使用 greet() 函式:

from mypackage import greet
print(greet())  # "Hello, Python!"

建立模組與子套件

建立模組(module1.py

每個模組可以定義自己專屬的函式與類別。例如:

# mypackage/module1.py
def greet():
    return "Hello, Python!"

建立子套件(subpackage/

若希望功能更細分,可以透過子套件進一步組織程式碼:

mypackage/
└── subpackage/
    ├── __init__.py
    ├── submodule1.py
    └── submodule2.py

在子套件的 __init__.py 中定義函式,便於使用者匯入:

# mypackage/subpackage/__init__.py
from .submodule1 import sub_function

def subpackage_greeting():
    return "Hello from subpackage!"

測試套件功能

要確認建立的套件是否正常運作,可以使用 Python 的互動式命令列進行測試:

  1. 移動到 mypackage 的上層目錄
cd path/to/your/package
  1. 啟動 Python 命令列
python
  1. 匯入套件並執行函式
import mypackage
print(mypackage.welcome())  # "Welcome to mypackage!"

小結

  • Python 套件 是由資料夾與 __init__.py 組成的結構。
  • __init__.py 用於識別與初始化套件。
  • 透過模組與子套件的分層設計,可提升程式碼的可讀性與組織性。
  • 建立後應在 Python 命令列中測試,確認功能是否正常。

4. 套件的匯入方式

匯入套件中的模組

使用 Python 套件時,通常會透過 import 陳述式進行匯入。假設有以下套件結構:

mypackage/
├── __init__.py
├── module1.py
├── module2.py
└── subpackage/
    ├── __init__.py
    ├── submodule1.py

直接匯入模組

假設 module1.py 中有定義一個 greet() 函式:

# mypackage/module1.py
def greet():
    return "Hello from module1!"

若要使用這個函式,可以這樣匯入:

import mypackage.module1

print(mypackage.module1.greet())  # Hello from module1!

使用 from 進行簡潔匯入

若希望匯入語法更簡潔,可以使用 from 陳述式:

from mypackage.module1 import greet

print(greet())  # Hello from module1!

相對匯入與絕對匯入的差異

在 Python 中,匯入同一套件中的其他模組時,可以使用 相對匯入絕對匯入 兩種方式。

絕對匯入(Absolute Import)

從專案的根目錄開始指定完整的模組路徑:

# mypackage/module2.py
from mypackage.module1 import greet

def call_greet():
    return greet()

這種方式的好處是可讀性高,結構清晰。

相對匯入(Relative Import)

以當前模組所在位置為基準,使用 . 來參照其他模組:

# mypackage/module2.py
from .module1 import greet

def call_greet():
    return greet()

使用 . 的數量可以表示層級,例如:

  • from .module1 import greet → 匯入同一層級的 module1.py
  • from ..subpackage.submodule1 import some_function → 匯入上一層的 subpackage/submodule1.py 中的 some_function

相對匯入 vs 絕對匯入

類型優點缺點
絕對匯入可讀性高,結構明確模組路徑較長,較繁瑣
相對匯入語法簡潔,適合內部模組之間的互相匯入從套件外部執行時可能出現錯誤(ImportError)

由於相對匯入在從套件外部執行時容易出現錯誤,因此在大型專案中通常建議使用 絕對匯入

利用 __init__.py 簡化匯入

可以在 __init__.py 中預先匯入常用函式或類別,讓外部使用時更加方便:

# mypackage/__init__.py
from .module1 import greet

這樣就能直接匯入套件並使用函式:

from mypackage import greet

print(greet())  # Hello from module1!

小結

  • 匯入模組的方法 包含 importfrom ... import 兩種方式。
  • 絕對匯入 結構清楚、可讀性高,但可能較冗長。
  • 相對匯入 語法簡潔,但從套件外部執行時可能產生錯誤。
  • 透過 __init__.py 簡化匯入 可以提升使用者體驗與套件易用性。
侍エンジニア塾

5. Python 套件的管理(活用 pip)

使用 pip 安裝與移除套件

在 Python 中,可以使用 pip 工具來輕鬆安裝外部函式庫。
透過 Python Package Index(PyPI) 官方套件庫下載並加入您的開發環境。

安裝套件

執行以下指令即可安裝指定套件:

pip install package_name

例如,若要安裝 requests 套件:

pip install requests

安裝完成後,即可在 Python 程式中透過 import 使用該套件:

import requests

response = requests.get("https://example.com")
print(response.status_code)

移除套件

若某套件不再需要,可使用 pip uninstall 將其移除:

pip uninstall package_name

例如,移除 requests 套件:

pip uninstall requests

執行後會出現確認提示,輸入 y 即可完成移除。

使用 pip freezerequirements.txt 來管理環境

在專案開發中,為了讓團隊成員或部署環境能安裝一致的套件版本,通常會建立 requirements.txt 檔案。

列出當前安裝的套件

使用下列指令可列出目前環境中已安裝的所有套件及其版本:

pip freeze

輸出範例:

requests==2.26.0
numpy==1.21.2
pandas==1.3.3

將此清單輸出成檔案,可使用:

pip freeze > requirements.txt

requirements.txt 一次安裝所有套件

當在新環境中部署專案時,可透過下列指令安裝 requirements.txt 中列出的所有套件:

pip install -r requirements.txt

使用虛擬環境(venv)管理套件

為了讓不同專案使用獨立的套件環境,建議使用 虛擬環境(venv)
這樣可以避免修改到系統全域的套件設定,提升穩定性與可維護性。

建立虛擬環境

進入專案資料夾,執行以下指令建立虛擬環境:

python -m venv myenv

這會建立名為 myenv/ 的資料夾,裡面包含專屬的 Python 執行環境。

啟動虛擬環境

啟用虛擬環境的方法如下:

  • Windows(PowerShell)
myenv\Scripts\Activate
  • Mac / Linux
source myenv/bin/activate

啟動後,指令列前方會出現 (myenv),表示已進入虛擬環境。

在虛擬環境中管理套件

啟用虛擬環境後,可以像平常一樣使用 pip 安裝套件:

pip install flask

若要離開虛擬環境,可輸入:

deactivate

套件版本管理

查看已安裝套件的版本

使用下列指令可查看所有已安裝套件的版本:

pip list

若想查看特定套件的詳細資訊,可使用:

pip show package_name

範例:

pip show numpy

輸出內容可能如下:

Name: numpy
Version: 1.21.2
Summary: NumPy 是用於陣列運算的核心套件。

更新套件至最新版本

可使用以下指令將套件升級至最新版:

pip install --upgrade package_name

例如:

pip install --upgrade requests

若要一鍵升級所有套件(限 Linux / Mac 環境),可使用:

pip list --outdated | awk '{print $1}' | xargs pip install --upgrade

(※ 需要系統中安裝 awkxargs

小結

  • pip install package_name 可安裝套件,pip uninstall 可移除。
  • 使用 pip freeze > requirements.txt 可記錄當前環境的所有套件,便於部署與版本控制。
  • 透過虛擬環境(venv)為不同專案建立獨立環境,避免相互干擾。
  • 使用 pip listpip install --upgrade 來管理與更新套件版本

6. Python 套件的發佈方式

使用 pyproject.toml 設定套件資訊

在 Python 中建立並發佈套件時,建議使用 pyproject.toml 來進行套件的設定與建構。這個檔案用來定義套件的中繼資料與相依套件資訊。

pyproject.toml 的基本結構

在專案的根目錄建立 pyproject.toml,並寫入以下內容:

[build-system]
requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "mypackage"
version = "0.1.0"
description = "My Python package"
authors = [{ name = "Your Name", email = "your_email@example.com" }]
license = { text = "MIT" }
dependencies = ["requests", "numpy"]

設定好之後,即可使用標準工具進行套件的建構與發佈。

使用 setuptools 建立套件

若要將套件製作成可發佈的格式(如 sdistwheel),可使用 setuptools 來打包。

準備套件的目錄結構

請確保您的專案結構如下:

mypackage/
├── mypackage/
│   ├── __init__.py
│   ├── module1.py
│   ├── module2.py
├── pyproject.toml
├── README.md
└── LICENSE
  • mypackage/(內層):實際的套件程式碼
  • pyproject.toml:套件設定檔
  • README.md:套件說明文件
  • LICENSE:授權資訊

建構套件

打開終端機並移動至專案根目錄,執行下列指令:

python -m build

執行後會在 dist/ 目錄中產生 .tar.gz(原始碼)與 .whl(wheel)格式的檔案:

dist/
├── mypackage-0.1.0-py3-none-any.whl
├── mypackage-0.1.0.tar.gz

使用 twine 發佈至 PyPI

若要將套件發佈到 PyPI,可使用 twine 工具。

先在 TestPyPI 測試上傳

建議先將套件上傳至 TestPyPI 進行測試,避免直接發佈錯誤內容。

首先安裝 twine

pip install twine

接著將套件上傳至 TestPyPI:

python -m twine upload --repository testpypi dist/*

要從 TestPyPI 安裝套件時,可使用以下指令:

pip install --index-url https://test.pypi.org/simple/ mypackage

正式發佈到 PyPI

確認測試無誤後,即可將套件發佈至正式的 PyPI

python -m twine upload dist/*

上傳後可以前往 https://pypi.org/ 搜尋您的套件並確認發佈成功。

從 PyPI 安裝套件

使用者可以透過以下指令安裝您發佈的套件:

pip install mypackage

小結

  • 使用 pyproject.toml 來管理套件資訊與建構設定。
  • 使用 python -m build 建立 sdistwhl 格式的發佈檔案。
  • 使用 twine 先將套件發佈至 TestPyPI 測試,確認無誤後再上傳至正式 PyPI。
  • 發佈後可透過 pip install 安裝並使用該套件。
年収訴求

7. 常見問題(FAQ)

__init__.py 是必需的嗎?

Q: 套件中一定要有 __init__.py 嗎?
A: 從 Python 3.3 開始,加入了 命名空間套件(Namespace Package) 的功能,即使沒有 __init__.py 也能被視為套件。
但在大多數開發實務中,仍然建議明確地建立 __init__.py,以提高相容性與可讀性。

# mypackage/__init__.py

您也可以在這個檔案中撰寫初始化邏輯,或預先匯出常用功能以簡化匯入。

什麼是相對匯入與絕對匯入?

Q: 相對匯入與絕對匯入有什麼差別?
A: 在 Python 中,可以使用兩種方式來匯入模組:

  • 絕對匯入(Absolute Import)
from mypackage.module1 import greet
  • 清楚標示完整路徑,結構明確
  • 可讀性高,不容易出錯
  • 相對匯入(Relative Import)
from .module1 import greet
  • 使用 . 表示與當前模組的相對位置
  • 當從套件外執行時,可能會出現 ImportError

套件與模組的命名有規則嗎?

Q: Python 套件與模組命名有沒有建議規範?
A: 根據 PEP8(Python 官方風格指南),建議使用以下命名方式:

  • 套件名稱:使用全小寫,簡短且具描述性
mypackage, utilities, datahandler
  • 模組名稱:同樣建議使用小寫並避免冗長
module1, parser, reader

requirements.txt 有什麼用途?

Q: requirements.txt 是做什麼用的?
A: requirements.txt 是用來記錄專案所依賴的所有套件與版本。這可協助團隊開發時維持一致的環境設定,並方便在部署或重建時還原相同環境。

可使用下列指令自動產生:

pip freeze > requirements.txt

在其他環境中安裝時,可使用:

pip install -r requirements.txt

為什麼會出現 ModuleNotFoundErrorImportError

Q: 匯入時出現 ModuleNotFoundErrorImportError,是什麼原因?該怎麼解決?
A: 這些錯誤通常是因為 Python 找不到模組或匯入路徑錯誤所導致。

錯誤類型可能原因解決方式
ModuleNotFoundError模組尚未安裝執行 pip install package_name
ImportError匯入路徑錯誤請改用絕對匯入方式測試

ModuleNotFoundError 的解法

  1. 確認套件是否已安裝:
pip list | grep package_name
  1. 若未安裝,請執行安裝:
pip install package_name

ImportError 的解法

  1. 嘗試使用絕對匯入:
from mypackage.module1 import greet
  1. 檢查執行目錄與模組路徑是否正確:
import sys
print(sys.path)

為什麼上傳到 PyPI 後無法 pip install

Q: 我已將套件上傳到 PyPI,但卻無法透過 pip install 安裝,為什麼?
A: 請檢查以下幾點:

  1. 確認上傳是否成功
twine check dist/*
  1. 確認使用正確的套件名稱
pip install mypackage
  1. 等待 PyPI 資料同步
  • 上傳後可能需等待數分鐘才會顯示在 PyPI。
  1. 如果是上傳到 TestPyPI
  • 請使用 --index-url 參數來指定來源:
pip install --index-url https://test.pypi.org/simple/ mypackage

小結

  • __init__.py 在 Python 3.3 之後雖非必需,但為相容性通常仍建議保留。
  • 絕對匯入 結構清晰、錯誤率低,推薦使用。
  • 善用 requirements.txt 管理相依套件,提高環境一致性。
  • ModuleNotFoundErrorImportError 通常可透過安裝套件與檢查匯入路徑解決。

8. 總結

Python 套件的基本概念

  • 模組 是單一的 .py 檔案,套件 則是包含多個模組的資料夾結構。
  • 函式庫 是由多個套件或模組所組成的軟體集合。
  • __init__.py 可用來識別套件並簡化匯入流程。

建立 Python 套件的方法

  • 建立 mypackage/ 資料夾並加入 __init__.py 即可作為套件。
  • 將功能分拆為多個模組,設計便於重複使用與維護的程式架構。
  • 使用 絕對匯入 能讓模組關係更清楚,利於維護與除錯。

套件的管理方式

  • 使用 pip install package_name 安裝套件,pip uninstall 可移除。
  • 透過 pip freeze > requirements.txt 將相依套件記錄下來,方便部署與分享。
  • 使用 python -m venv myenv 建立虛擬環境,為每個專案提供獨立的開發環境。

套件的發佈方式

  • 使用 pyproject.toml 設定套件資訊與建構方式。
  • 透過 python -m build 產生可發佈的檔案至 dist/ 目錄中。
  • 先使用 twine 上傳至 TestPyPI 測試,確認正常後再發佈至 PyPI
  • 套件發佈後,可使用 pip install mypackage 進行安裝。

常見錯誤與對策

  • ModuleNotFoundError 通常是因為套件尚未安裝或路徑錯誤,可透過 pip install 解決。
  • ImportError 常見於相對匯入時,可改用絕對匯入方式避免問題。
  • 使用 pip list --outdated 可查詢過期套件,搭配 pip install --upgrade 進行更新。

Python 套件管理的最佳實踐

  1. 遵循命名規範
  • 套件與模組名稱建議使用簡潔的小寫字母,提升可讀性與一致性。
  1. 善用虛擬環境(venv)
  • 避免影響全域環境,讓專案間相互獨立。
  1. 隨時維護 requirements.txt
  • 能幫助團隊合作與部署過程更順利,減少環境差異造成的錯誤。
  1. 發佈前先在 TestPyPI 測試
  • 能事先發現錯誤,確保上架品質與安裝體驗。

總結與進階學習方向

掌握 Python 套件的架構與管理方式後,您將能更有效率地開發與重用程式碼。
善用虛擬環境與標準化工具,將有助於打造更穩定與專業的開發流程。

接下來,您可以進一步學習以下主題,拓展技術深度:

  • 進階套件開發技巧(如加入自訂指令、整合 C 擴充)
  • 使用 CI/CD 自動化套件部署流程
  • 結合 Docker 建立一致的開發與部署環境

希望本教學能幫助您更加理解 Python 套件的應用與發佈流程。
感謝您的閱讀!