[Python] docopt

今天因為要在程式加上 optionParser 發現 python v2.7 不支援了

只好找尋其他 library使用, 我也知道其實早就有 argparser

可是就覺得他好難用, 當初要寫他文件就寫得很零碎

今天 google 了一番, 發覺有個東西叫 docopt, 好像好好用阿, 就來試用一下

一用之下, 真是令人清爽, 而且強迫你建立好習慣, 是個好 library

Official site: http://docopt.org/

pip: https://pypi.python.org/pypi/docopt


基本範例

"""
Usage:
  testd [start | stop | restart] [-e <file> ... | --exec <file> ...]
  testd (-h | --help | -v | --version)
  testd (-d) [-q | --quiet] [-olb]

This is a test option program

Options:
  -h --help     Show this screen.  # Just a help
  -v --version  Show version.
  -q --quiet    Quiet Mode
  -d            Demo mode
  -o            online
  -l            line number
  -b            background
  -e <file> --exec <file>  execute file. [default: /usr/local/bin/g++]
  start         Start testd as service
  stop          Stop testd service
  restart       Restart testd service

"""

from docopt import docopt

if __name__ == "__main__":
    arguments = docopt(__doc__, argv=None, help=True, version='v1.0', options_first=False)
    print(arguments)

就這樣!! 寫完了

你會說, 甚麼? 程式碼才剛宣告完畢而以阿!!

其實他就是利用你撰寫 doc string 的時候, 順便完成 option implement

也就是強迫你養成好習慣寫程式的使用方式, 還可以順便寫完 parser

當然, 猜的出來其實背後應該有一定的規則跟使用, 不是你隨便寫寫就可以的

我一開始看到這種東西的時候, 第一個問題是, 那如果我有其他 doc string 也要放不就干擾了?

可是要是仔細看, 他其實 docopt 吃的第一個參數才會有作用, 所以並非一定是程式的 doc string

你也可以把這東西存成某一變數, 傳給他即可

ex:
option = """
Usage:
  testd [start | stop | restart] [-e <file> ... | --exec <file> ...]
  testd (-h | --help | -v | --version)
  testd (-d) [-q | --quiet] [-olb]

This is a test option program

Options:
  -h --help     Show this screen.  # Just a help
  -v --version  Show version.
  -q --quiet    Quiet Mode
  -d            Demo mode
  -o            online
  -l            line number
  -b            background
  -e <file> --exec <file>  execute file. [default: /usr/local/bin/g++]
  start         Start testd as service
  stop          Stop testd service
  restart       Restart testd service

"""

from docopt import docopt

if __name__ == "__main__":
    arguments = docopt(option, argv=None, help=True, version='v1.0', options_first=False)
    print(arguments)

這樣也行!!

因為他規則要遵守才能開始, 所以下面一項一項來解釋, docopt最後再來解說

Usage

Usage:
  testd [start | stop | restart] [-e <file> ... | --exec <file> ...]
  testd (-h | --help | -v | --version)
  testd (-d) [-q | --quiet] [-olb]


先從上面開始可以看出, 需要兩區塊, 一個是 Usage, 一個是 Options

Usage(大小寫都可以) 就是使用方法, Options 就是說明參數的含意

我這邊 Usage 看起來好像很複雜, 其實並不會XD

在 Usage 這邊, 每一個中括號 [], 就是可有可無的存在, | 分隔線也就是只會出現一種 case

開頭 testd 當然就是你程式的執行名稱啦~

後續下面會分段說明

Case 1.
testd [start | stop | restart]

這意思就是, 我可以輸入 testd start, 或者是 testd stop, testd restart

但是不可以是 testd start stop, 則會錯誤, 當然也可以都不打, 就只有 testd

Case 2.
testd [-e=<file> ...| --exec=<file> ...]

這邊則是說如果我輸入的是 -e, 那必須要給後續的參數, 例如 testd -e /usr/local/bin/c++

這邊有個 ... , 意思就是可以輸入多筆, 例如 testd -e /usr/bin/python -e /usr/bin/R

他存起來會存成 list

Case 3.
testd (-d) [-q | --quiet] [-olb]

如果今天出現的是小括號(), 也就是說一定要出現

意思就是, 你不能打 testd -q, 這樣的會出現命令錯誤, 但是你可以只打 testd -d, 因為 [] 可省略

當然也可以打 test -d -q

而其實他也可以堆疊在一起使用(stack), 也就是可以下 testd -d -o -l -b 或者是 testd -d -olb

而 Usage 的區塊寫完記得 要空一行代表結束

基本上已經完成一半了, 整理如下

(), 就是必須給定的(require), [] 就是選擇性的(option), 注意, 這邊 option 大小寫要區分

| 就是互斥的 (pipe), ... 就是多項 (ellipsis)

Option

再來是 Option 區塊

Options:
  -h --help     Show this screen.  # Just a help
  -v --version  Show version.
  -q --quiet    Quiet Mode
  -d            Demo mode
  -o            online
  -l            line number
  -b            background
  -e <file> --exec <file>  execute file. [default: /usr/local/bin/g++]
  start         Start testd as service
  stop          Stop testd service
  restart       Restart testd service

Option 要說明哪些是長版跟短版的選項(-, or --), 或者是有沒有 default 值也是在此設定

1. 每一項開頭一定都是 - or --

2. 如果有長版跟短版, 之間空一格即可, 例如 -h --help

3. 如果參數後面要接輸入值, 用<>包起來或者是用=, 例如 -e <file>  或者是 -e=file

4. 要如何區分參數跟後面的描述? 請至少用兩個空格隔開, 例如 -h --help  Show this screen

5. 設定 default值很簡單, 描述的後面放入 [default: 你的default值]

基本上用法就是這樣

docopt

最後最重要的, docopt instance

docopt(option, argv=None, help=True, version='v1.0', options_first=False)

參數

第一個放的當然就是要傳入分析的 option

第二個參數是除了外部的 stdin, 你也可以直接強制給有哪些 option先餵給 docopt
(通常是測試用)

第三個, 內建 help, 也就是如果你參數有 -h 是要用來印出剛剛設定的說明, 這邊給 True

他程式實際上就會幫你印出 help, 如果 False, 就表示你 -h 有其他用途, 他就不會印 help

第四個, 內建 version, 跟 help 類似, 只是如果後面打 string, 你下 testd -v, 就只會印出你設定的version
(不要 version 的話給 None 即可)

第五個, 就是準不準同時使用 option 跟 positional 的參數方式, 舉例說明較快

如果 options_first=True

testd start -e /usr/bin/g++ ; 允許
testd -e /usr/bin/g++  ; 允許
testd start -e /usr/bin/g++  ; 不允許

那然後呢? 其實就我的範例, 他會把他用 dict 的方式存在 arguments

後面就用一般的 arguments 存取即可

例如我如果都不輸入得到的結果是

{'--exec': ['/usr/local/bin/g++'],
 '--help': False,
 '--quiet': False,
 '--version': False,
 '-b': False,
 '-d': False,
 '-l': False,
 '-o': False,
 '-q': False,
 'restart': False,
 'start': False,
 'stop': False}

看得出來 key 跟 option 的關系應該很清楚了

# 其實我也沒有摸很久, 只是覺得不錯, 花點時間寫好用法XD, 有問題歡迎提出

留言

這個網誌中的熱門文章

[Linux] Linux下查詢硬體記憶體資訊 Memory Information

[Other] Chrome 重新整理所有開啟頁面

[Python] Simple Socket Server