Python 指令行之旅:初探 docopt
原文發表于
Prodesire 部落格。
一、前言
在本系列前面四篇文章中,我們介紹了
argparse
的方方面面。它無疑是強大的,但使用方式上略顯麻煩。需要先設定解析器,再定義參數,再解析指令行,最後實作業務邏輯。
而今天要介紹的
docopt則是站在一個全新的視角來審視指令行。你可曾想過,一個指令行程式的幫助資訊其實已然包含了這個指令行的完整元資訊,那麼是否可以通過定義幫助資訊來定義指令行呢?
docopt
就是基于這樣的想法去設計的。
本系列文章預設使用 Python 3 作為解釋器進行講解。
若你仍在使用 Python 2,請注意兩者之間文法和庫的使用差異哦~
二、介紹
基于長久以來在幫助資訊和手冊中描述程式接口的約定,其接口描述是形式化的幫助資訊。它能夠根據指令行程式中定義的接口描述,來自動生成解析器。
三、快速開始
3.1 定義接口描述/幫助資訊
第一步要做的就是指令行程式的定義接口描述或者是幫助資訊,這樣
docopt
就能知道指令行的元資訊,進而自動解析。
接口描述通常定義在一個子產品的文檔字元串中,我們仍然以在
Python 指令行之旅:初探 argparse
的例子為例,講解如何使用
docopt
來定義接口描述。
在
cmd.py
中,我們定義如下接口描述:
"""Num accumulator.
Usage:
cmd.py [--sum] <num>...
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,
'<num>': ['1', '2', '3']}
可以看到:
- 沒有提供
或者-h
,是以--help
中arguments
為--help
False
- 提供了
--sum
arguments
--sum
True
-
<num>...
1 2 3
arguments
<num>
['1', '2', '3']
3.3 業務邏輯
獲得了解析後的指令行參數,我們就可以根據自己的業務需求做進一步處理了。
在本文示例中,我們希望當使用者提供
--sum
選項時,是對給定的一組數字求和;反之則是取最大值,那麼就可以這麼寫:
nums = (int(num) for num in arguments['<num>'])
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] <num>...
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['<num>'])
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
的思路非常簡單,就是定義接口描述,然後幫你解析指令行為參數字典,接下來就根據這個字典來編寫業務邏輯。
重點就是在于如何定義接口描述,在下一篇文章中,我們來深入了解下如何定義指令、選項、位置參數等接口描述。