讓你如紳士般基於描述編寫 Python 命令行工具的開源項目:docopt


讓你如紳士般基於描述編寫 Python 命令行工具的開源項目:docopt


作者:HelloGitHub-Prodesire

一、前言

在本系列前面四篇文章中,我們介紹了 argparse 的方方面面。它無疑是強大的,但使用方式上略顯麻煩。需要先設置解析器,再定義參數,再解析命令行,最後實現業務邏輯。

而今天要介紹的 docopt[1] 則是站在一個全新的視角來審視命令行。你可曾想過,一個命令行程序的幫助信息其實已然包含了這個命令行的完整元信息,那麼是否可以通過定義幫助信息來定義命令行呢?docopt 就是基於這樣的想法去設計的。

本系列文章默認使用 Python 3 作為解釋器進行講解。
若你仍在使用 Python 2,請注意兩者之間語法和庫的使用差異哦~

二、介紹

docopt[2] 基於長久以來在幫助信息和手冊中描述程序接口的約定,其接口描述是形式化的幫助信息。它能夠根據命令行程序中定義的接口描述,來自動生成解析器。

三、快速開始

3.1 定義接口描述/幫助信息

第一步要做的就是命令行程序的定義接口描述或者是幫助信息,這樣 docopt 就能知道命令行的元信息,從而自動解析。

接口描述通常定義在一個模塊的文檔字符串中,我們仍然以在 Python 命令行之旅:初探 argparse 的例子為例,講解如何使用 docopt 來定義接口描述。

在 cmd.py 中,我們定義如下接口描述:

"""Num accumulator.
Usage:
cmd.py [--sum] ...
cmd.py (-h | --help)
Options:
-h --help Show help.
--sum Sum the nums (default: find the max).
"""

在上面的接口描述中,我們定義了命令行程序 cmd.py 接受一個或多個數字 num,而 --sum 選項則是可選,-h 或 --help 則輸出幫助信息。

若提供 --sum,則累加給定的數字;反之,取給定多個數字中最大的一個。這個業務邏輯我們將在後文實現。

3.2 解析命令行

定義好接口描述後,就可以使用 docopt 進行解析,寫法非常簡單:

from docopt import docopt
arguments = docopt(__doc__, options_first=True)
print(arguments)

由於我們之前是將接口描述定義在模塊的文檔字符串中,那麼直接使用 __doc__ 即可獲得接口描述。然後使用 docopt 函數即可解析命令行為參數字典。為了支持負數,我們將 options_first 設置為 True。

當我們執行 python3 cmd.py --sum 1 2 3 時,將會得到如下內容:

{'--help': False,
'--sum': True,
'': ['1', '2', '3']}

可以看到:

  • 沒有提供 -h 或者 --help,所以 arguments 中 --help 為 False
  • 提供了 --sum,所以 arguments 中 --sum 為 True
  • 提供了 ... 為 1 2 3,所以 arguments 中 為 ['1', '2', '3']

3.3 業務邏輯

獲得瞭解析後的命令行參數,我們就可以根據自己的業務需求做進一步處理了。在本文示例中,我們希望當用戶提供 --sum 選項時,是對給定的一組數字求和;反之則是取最大值,那麼就可以這麼寫:

nums = (int(num) for num in arguments[''])
if arguments['--sum']:
result = sum(nums)
else:
result = max(nums)
print(result) # 基於上文的 python3 cmd.py --sum 1 2 3 參數,其結果為 6

3.4 代碼梳理

使用 docopt 的方式非常簡單,我們將上文的代碼彙總下,以有一個更清晰的認識:

# cmd.py
# 1. 定義接口描述
"""Num accumulator.
Usage:
cmd.py [--sum] ...

cmd.py (-h | --help)
Options:
-h --help Show help.
--sum Sum the nums (default: find the max).
"""
from docopt import docopt
# 2. 解析命令行
arguments = docopt(__doc__, options_first=True)
# 3. 業務邏輯
nums = (int(num) for num in arguments[''])
if arguments['--sum']:
result = sum(nums)
else:
result = max(nums)
print(result)

若我們需要對一組數字求和,只需執行:

$ python3 cmd.py --sum 1 0 -1
0

若我們需要對一組數字求最大值,只需執行:

$ python3 cmd.py 1 0 -1
1

我們還可以通過 -h 或 --help 參數查看使用說明和幫助,也就是我們定義的接口描述。

四、小節

docopt 的思路非常簡單,就是定義接口描述,然後幫你解析命令行為參數字典,接下來就根據這個字典來編寫業務邏輯。

重點就是在於如何定義接口描述,在下一篇文章中,我們來深入瞭解下如何定義命令、選項、位置參數等接口描述。

[1] docopt: http://docopt.org/

[2] docopt: http://docopt.org/

『講解開源項目系列』——讓對開源項目感興趣的人不再畏懼、讓開源項目的發起者不再孤單。跟著我們的文章,你會發現編程的樂趣、使用和發現參與開源項目如此簡單。歡迎留言聯繫我們、加入我們,讓更多人愛上開源、貢獻開源~


分享到:


相關文章: