Python 提供豐富的函式庫和框架,簡化命令列應用程式開發。本文介紹 argparse、docopt、Click、Clint 和 Cliff 等工具,並比較它們的特性與使用場景。argparse 適合處理標準命令列引數,docopt 則從檔案字串解析,Click 提供高度可組裝性,Clint 增強命令列介面顯示效果,Cliff 適用於複雜多層級命令結構。開發者可根據專案規模和需求選擇合適的工具,提升開發效率。此外,文章也簡述 GUI 開發的常用 Python 工具包,方便讀者進一步探索。
命令列應用程式
命令列應用程式(Command-line Applications)是指設計用於從文字介面(如 shell)使用的電腦程式。它們可以是簡單的命令,例如 pep8 或 virtualenv,也可以是互動式的,如 Python 直譯器或 ipython。某些命令列應用程式具有子命令,例如 pip install、pip uninstall 或 pip freeze,這些子命令除了擁有 pip 的一般選項外,還有自己的選項。所有這些應用程式都可能在 main() 函式中啟動;我們的 BDFL(終身仁慈獨裁者)已經分享了他對什麼是好的 main() 函式的看法。
讓我們使用一個 pip 呼叫的範例來說明呼叫命令列應用程式時可能存在的元件:
$ pip install --user -r requirements.txt
在這個範例中:
pip是被呼叫的可執行檔名稱,即命令。install是引數或子命令。--user和-r requirements.txt是選項或旗標。
命令列工具函式庫
表格 7-1 中列出的函式庫都為解析命令列引數提供了不同的選項,或為命令列應用程式提供了其他有用的工具。
表格 7-1. 命令列工具
| 函式庫名稱 | 授權條款 | 使用理由 |
|---|---|---|
| argparse | PSF 授權 | • 內建於 Python 標準函式庫。 • 提供標準的引數和選項解析功能。 |
| docopt | MIT 授權 | • 允許控制幫助訊息的佈局。 • 根據 POSIX 標準定義的實用工具慣例解析命令列。 |
| plac | BSD 3-條款授權 | • 從現有的函式簽名自動生成幫助訊息。 • 在幕後解析命令列引數,並直接將它們傳遞給你的函式。 |
| click | BSD 3-條款授權 | • 提供裝飾器來製作幫助訊息和解析器(與 plac 類別似)。 • 允許組合多個子命令。 • 與其他 Flask 外掛程式介面(Click 獨立於 Flask,但最初是為了幫助使用者組合來自不同 Flask 外掛程式的命令列工具而不破壞任何東西而編寫的,因此它已經在 Flask 生態系統中使用)。 |
| clint | 網際網路軟體聯盟(ISC)授權 | • 為你的文字輸出提供格式化功能,如顏色、縮排和欄位顯示。 • 在互動式輸入中提供型別檢查(例如,檢查正規表示式、整數或路徑)。 • 提供直接存取引數列表的功能,並具有一些簡單的篩選和分組工具。 |
| cliff | Apache 2.0 授權 | • 為具有多個子命令的大型 Python 專案提供結構化的框架。 • 建立一個互動式環境來使用子命令,無需額外的編碼。 |
通常,你應該首先嘗試使用 Python 標準函式庫中提供的工具,只有當它們無法滿足你的需求時,才將其他函式庫新增到你的專案中。
argparse
argparse 模組(取代了現在已棄用的 optparse)存在於 Python 的標準函式庫中,用於幫助解析命令列選項。HowDoI 專案提供的命令列介面使用了 argparse;在建立你自己的命令列介面時,可以參考它。
argparse 使用範例
import argparse
def get_parser():
parser = argparse.ArgumentParser(description='...為了簡潔而截斷...')
parser.add_argument('query', metavar='QUERY', type=str, nargs='*',
help='要回答的問題')
parser.add_argument('-p','--pos',
help='選擇指定位置的答案(預設:1)',
default=1, type=int)
parser.add_argument('-a','--all', help='顯示答案的全文',
action='store_true')
parser.add_argument('-l','--link', help='僅顯示答案連結',
action='store_true')
parser.add_argument('-c', '--color', help='啟用彩色輸出',
action='store_true')
parser.add_argument('-n','--num-answers', help='傳回的答案數量',
default=1, type=int)
parser.add_argument('-C','--clear-cache', help='清除快取',
action='store_true')
parser.add_argument('-v','--version',
help='顯示 howdoi 的當前版本',
action='store_true')
return parser
argparse 程式碼解密:
argparse.ArgumentParser()用於建立一個解析器物件。add_argument()方法用於定義命令列引數和選項。action='store_true'表示該選項是一個旗標,如果出現在命令列中,則在解析器的字典中儲存為True。- 解析器將解析命令列並建立一個字典,該字典將每個引數對映到一個值。
docopt
docopt 的核心哲學是檔案應該是美觀且易於理解的。它提供了一個主要命令 docopt.docopt(),以及一些為高階使用者提供的便利函式和類別。docopt.docopt() 函式接受開發者編寫的 POSIX 風格的使用說明,並使用它們來解釋使用者的命令列引數,然後傳回一個包含從命令列解析的所有引數和選項的字典。它還適當地處理 --help 和 --version 選項。
docopt 使用範例
#!/usr/bin/env python3
"""向你打招呼。
用法:
hello <name>... [options]
hello -h | --help | --version
選項:
-c, --capitalize 是否將名字大寫
-n REPS, --num_repetitions=REPS 重複次數 [預設:1]
"""
__version__ = "1.0.0" # 為了 --version 所需
def hello(name, repetitions=1):
for rep in range(repetitions):
print('Hello {}'.format(name))
if __name__ == "__main__":
from docopt import docopt
arguments = docopt(__doc__, version=__version__)
if arguments['<name>']:
name = arguments['<name>'][0]
repetitions = int(arguments['--num_repetitions'])
hello(name, repetitions)
docopt 程式碼解密:
- 使用
""" """檔案字串定義了程式的使用說明和選項說明。 docopt(__doc__, version=__version__)解析命令列引數並傳回一個字典。- 根據解析結果,呼叫
hello()函式並傳遞相應的引數。
命令列應用程式開發工具比較與實務應用
在開發命令列應用程式時,開發者有多種工具可供選擇,包括 docopt、Plac、Click 和 Clint 等。這些工具各具特色,能夠簡化命令列引數的解析和處理流程,提升開發效率。本文將探討這些工具的特點、用法及實際應用場景。
Docopt:根據檔案字串的命令列引數解析
Docopt 是一種創新的命令列引數解析工具,它利用函式的檔案字串(docstring)來定義命令列介面。Docopt 能夠根據檔案字串中的特定格式解析命令列引數,並將其轉換為 Python 物件。
程式碼範例:使用 Docopt 解析命令列引數
arguments = docopt(__doc__, version=__version__)
name = ' '.join(arguments['<name>'])
repetitions = arguments['--num_repetitions']
if arguments['--capitalize']:
name = name.upper()
hello(name, repetitions=repetitions)
內容解密:
docopt(__doc__, version=__version__):使用檔案字串和版本資訊初始化 Docopt。arguments['<name>']和arguments['--num_repetitions']:從解析結果中提取命令列引數。--capitalize選項用於控制是否將名字大寫。
Plac:根據函式簽名的命令列引數解析
Plac 是一種輕量級的命令列引數解析工具,它透過分析目標函式的簽名來推斷命令列引數的結構。Plac 簡化了命令列應用程式的開發流程。
程式碼範例:使用 Plac 定義命令列介面
import plac
def hello(name, capitalize=False, repetitions=1):
"""向你打招呼。"""
if capitalize:
name = name.upper()
for rep in range(repetitions):
print('Hello {}'.format(name))
if __name__ == "__main__":
plac.call(hello)
內容解密:
plac.call(hello):呼叫hello函式並根據命令列引數執行。- 函式簽名
def hello(name, capitalize=False, repetitions=1)定義了命令列引數的結構。
Click:高度可組裝的命令列介面建立工具
Click 是一種功能強大的命令列介面建立工具,旨在簡化複雜命令列應用程式的開發。它提供了豐富的功能和高度的可組態性。
程式碼範例:使用 Click 建立命令列應用程式
import click
@click.command()
@click.argument('name', type=str)
@click.option('--capitalize', is_flag=True)
@click.option('--repetitions', default=1, help="重複問候的次數。")
def hello(name, capitalize, repetitions):
"""向你打招呼,可選擇是否大寫名字和重複次數。"""
if capitalize:
name = name.upper()
for rep in range(repetitions):
print('Hello {}'.format(name))
if __name__ == '__main__':
hello()
內容解密:
@click.command()和@click.argument()、@click.option()裝飾器用於定義命令列介面。is_flag=True表示--capitalize是一個標誌選項。default=1為--repetitions選項設定了預設值。
Clint:豐富的命令列介面工具集
Clint 提供了一系列用於增強命令列介面的工具,包括彩色輸出、縮排和進度條等功能,使命令列應用程式更加友好和易用。
程式碼範例:使用 Clint 實作彩色輸出和縮排
from clint.arguments import Args
from clint.textui import colored, indent, puts
def hello(name, capitalize, repetitions):
if capitalize:
name = name.upper()
with indent(5, quote=colored.magenta(' ~*~', bold=True)):
for i in range(repetitions):
greeting = 'Hello {}'.format(colored.green(name))
puts(greeting)
if __name__ == '__main__':
args = Args()
# 處理幫助訊息和其他命令列引數
name = " ".join(args.grouped['_'].all)
capitalize = args.any_contain('-c')
repetitions = int(args.value_after('--reps') or 1)
hello(name, capitalize=capitalize, repetitions=repetitions)
內容解密:
indent(5, quote=colored.magenta(' ~*~', bold=True)):設定縮排和引導符號。colored.green(name)和colored.magenta(' ~*~', bold=True):實作彩色輸出。puts(greeting):輸出問候訊息並處理縮排和引導符號。
命令列介面框架與圖形使用者介面開發
在開發命令列介面(CLI)應用程式時,Python 提供了多種框架和函式庫來簡化開發流程。其中,cliff 是一個強大的框架,用於建立具有多層級命令結構的 CLI 程式,如 svn 或 git。另一方面,在圖形使用者介面(GUI)開發方面,Python 提供了多種工具包和框架,以簡化視窗元件的建立和管理。
使用 cliff 框架建立 CLI 應用程式
cliff 是一個用於建立 CLI 程式的框架,它提供了抽象基礎類別來組織功能。開發者需要實作 cliff.command.Command 類別以定義子命令,並使用 cliff.commandmanager.CommandManager 來管理這些命令。
建立一個簡單的 CLI 應用程式
以下是一個使用 cliff 的簡單範例:
import sys
from argparse import ArgumentParser
from pkg_resources import get_distribution
from cliff.app import App
from cliff.command import Command
from cliff.commandmanager import CommandManager
__version__ = get_distribution('HelloCliff').version
class Hello(Command):
"""對某人說你好。"""
def get_parser(self, prog_name):
parser = ArgumentParser(description="Hello 命令", prog=prog_name)
parser.add_argument('--num', type=int, default=1, help='重複次數')
parser.add_argument('--capitalize', action='store_true')
parser.add_argument('name', help='人名')
return parser
def take_action(self, parsed_args):
if parsed_args.capitalize:
name = parsed_args.name.upper()
else:
name = parsed_args.name
for i in range(parsed_args.num):
self.app.stdout.write("Hello from cliff, {}.\n".format(name))
class MyApp(App):
def __init__(self):
super(MyApp, self).__init__(
description='Cliff 中的最小應用程式',
version=__version__,
command_manager=CommandManager('named_in_setup_py'),
)
def main(argv=sys.argv[1:]):
myapp = MyApp()
return myapp.run(argv)
內容解密:
- 匯入必要的模組:首先,範例程式碼匯入了必要的模組,包括
argparse用於解析命令列引數,cliff.app、cliff.command和cliff.commandmanager用於建立 CLI 應用程式。 - 定義
Hello命令:Hello類別繼承自cliff.command.Command,並實作了get_parser和take_action方法。get_parser方法定義了命令的引數,而take_action方法則定義了當命令被呼叫時執行的動作。 - 定義主應用程式類別
MyApp:MyApp類別繼承自cliff.app.App,負責設定應用程式的全域屬性,如日誌、I/O 流等。 - 主函式:
main函式建立了MyApp的例項並執行它。
圖形使用者介面(GUI)開發
在 GUI 開發方面,Python 提供了多種工具包和框架,如 Tkinter、Kivy、PyQt 和 wxPython 等。這些工具包提供了豐富的視窗元件,如按鈕、捲軸和文字方塊等,以簡化 GUI 的開發。
常用的 GUI 工具包
| 底層函式庫(語言) | Python 函式庫 | 授權條款 | 使用理由 |
|---|---|---|---|
| Tk (Tcl) | tkinter | Python 軟體基金會授權條款 | 所有相依性已包含在 Python 中,提供標準的 UI 元件。 |
| SDL2 (C) | Kivy | MIT 或 LGPL3(1.7.2 之前) | 可用於建立 Android 應用程式,支援多點觸控,使用 GPU 最佳化。 |
| Qt (C++) | PyQt | GNU 通用公共授權條款(GPL)或商業授權 | 提供跨平台的一致性外觀和感覺,已被許多應用程式和函式庫使用。 |
| GTK (C) | PyGObject | GNU 較寬通用公共授權條款(LGPL) | 為 GTK+ 3 提供 Python 繫結,應對已熟悉 GNOME 桌面系統開發的人來說很熟悉。 |
內容解密:
- 多樣化的 GUI 工具包:Python 提供了多種 GUI 工具包,以滿足不同的開發需求和偏好。
- 選擇合適的工具包:開發者可以根據專案需求、目標平台和個人偏好選擇合適的 GUI 工具包。
- 跨平台支援:許多 GUI 工具包提供了跨平台支援,使得開發者能夠在多個作業系統上佈署應用程式。
總之,Python 為 CLI 和 GUI 應用程式的開發提供了豐富的框架和工具包。開發者可以根據專案需求選擇合適的工具,以簡化開發流程並提高生產力。