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

  • 2019 年 10 月 9 日
  • 筆記


作者:HelloGitHub-Prodesire

HelloGitHub 的《講解開源項目》系列,項目地址:https://github.com/HelloGitHub-Team/Article

一、前言

在本系列前面四篇文章中,我們介紹了 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 中 --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 的思路非常簡單,就是定義介面描述,然後幫你解析命令行為參數字典,接下來就根據這個字典來編寫業務邏輯。

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


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

Tags: