Python 命令行之旅:初探 docopt

Python 命令行之旅:初探 docopt

原文發表於 Prodesire 博客

一、前言

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

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

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

二、介紹

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

三、快速開始

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--helpFalse
  • 提供了 --sum,所以 arguments--sumTrue
  • 提供了 <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 的思路非常簡單,就是定義接口描述,然後幫你解析命令行爲參數字典,接下來就根據這個字典來編寫業務邏輯。

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章