通過命令行運行腳本,設置合理的命令或者參數,可以讓腳本使用更加友好,避免頻繁修改源文件中的hard code導致的效率低下問題。
同時,這是也是踐行python的理念,讓程序變得更加Pythonic!更酷!
一 介紹
開發過程中我們可能需要讓我們的程序接受一些參數,以便執行不同的功能,而不需要修改代碼。
爲了實現這個功能,我們可以自己解析main函數的參數列表,也可以使用一些命令行工具。
命令行工具有很多,比如argparse
,fire
,docopt
,當然,包括click
,不同工具有不同的“屬性”,選擇最合適自己習慣的一款即可。
命令行常用的參數類型:
- 參數,必須要設定的值,以便程序能夠運行,比如
find
命令必須指定路徑 - 選項,可選的參數,可以是各種類型,開關,數值,區間等等,比如
ls
命令可以指定路徑,否則默認是當前路徑 - 子命令,給主命令添加子命令,同樣可以擁有各種參數,類似
git config
,config
就是git
支持的子命令,config
也有自己的參數
二 安裝
使用pip3安裝click:
pip3 install --user click
--user
表示安裝到用戶目錄,更多時候都建議使用這個選項,可以避免一些權限問題。
三 使用
使用Click的一般步驟爲:
- 使用
@click.command()
裝飾指定函數,使之成爲命令行接口; - 使用
@click.argument()
或者@click.option()
裝飾函數,爲其添加命令行選項等。
1 最簡單的示例
下面是click的最簡單的形式,後續以此爲框架實現不同功能。
使用@click.command()
修飾函數main,就可以讓它成爲一條命令,目前它只能接受參數--help
。
import click
@click.command()
def main():
print('Hello click')
if __name__ == "__main__":
main()
通過命令行執行可以正常輸出,如果指定--help
則會打印出它的幫助內容。如下:
# python3 click_demo.py
Hello click
# python3 click_demo.py --help
Usage: click_demo.py [OPTIONS]
Options:
--help Show this message and exit.
2 添加必備參數
在click中,通過@click.argument('param-name')
指定必備參數。
click會將參數名解析爲"param_name"
,即去掉前綴,橫線改下劃線傳遞給main函數,如果參數命名對不上,則會報錯。
如下(代碼基於前面的修改,以下只展示修改部分):
@click.command()
@click.argument('user-name')
def main(user_name):
print(f'Hello {user_name}')
此時執行help得到的提示是:
# python3 click_demo.py --help
Usage: click_demo.py [OPTIONS] USER_NAME
Options:
--help Show this message and exit.
其中全大寫加下劃線表示是必備參數,如果執行時不指定則會報錯:
# python3 click_demo.py
Usage: click_demo.py [OPTIONS] USER_NAME
Try 'click_demo.py --help' for help.
Error: Missing argument 'USER_NAME'.
指定參數時則正常運行:
# python3 click_demo.py farmer
Hello farmer
click.argument()
還可以指定參數類型、獲取環境變量、選擇項參數等功能,詳見arguments。
3 添加可選參數
在click中,通過@click.option( )
指定必備參數,以下是幾種常用的方法:
-
指定參數縮寫、完整名稱、自定義解析後的變量名、設置默認值和參數解釋:
@click.option('-p', '--param-name', 'custom_param_name', default='magic', help='Parameter introduce.')
-
只指定完整參數名(對應變量名將按約定方式命名),指定參數類型(默認爲str),未指定參數時提示用戶輸入:
@click.option('--count', type=int, prompt='Input greet times', help='The times to greet.')
-
設定一個開關標識位,不接受參數值(這是一個trick,有更好的實現方式):
@click.option('-d', '--debug', is_flag=True, help='Enable debug mode')
將main函數修改如下:
@click.command()
@click.argument('user-name')
@click.option('-p', '--param-name', 'custom_param_name', default='magic', help='Parameter introduce.')
@click.option('--count', type=int, prompt='Input greet times', help='The times to greet.')
@click.option('-d', '--debug', is_flag=True, help='Enable debug mode')
def main(user_name, custom_param_name, count, debug):
if debug:
print(f'Enter debug mode')
for i in range(count):
print(f'Greet {i}: Hello {user_name}')
print(f'Custom parameter is: {custom_param_name}')
此時help輸出的結果是:
# python3 click_demo.py --help
Usage: click_demo.py [OPTIONS] USER_NAME
Options:
-p, --param-name TEXT Parameter introduce.
--count INTEGER The times to greet.
-d, --debug Enable debug mode
--help Show this message and exit.
此時參數已經變得豐富了,此時:
- 使用時必須指定參數
USER_NAME
; - 可以通過
-p
或者--param-name
指定該參數的值,默認類型爲字符串; - 可以通過
--count=3
或者--count 3
指定問候語打印次數爲3次,類型爲整型;如果沒有指定,則會提示用戶輸入,並自動轉換爲整型;如果輸入的字符串不能轉換爲整數,則會提示再次輸入; - 如果指定
-d
或者--debug
則開啓調試模式;默認爲false,程序中獲取到的值爲None。
以下是一些演示:
# python3 click_demo.py farmer --count 3 -p 123
Greet 0: Hello farmer
Greet 1: Hello farmer
Greet 2: Hello farmer
Custom parameter is: 123
# python3 click_demo.py farmer -d
Input greet times: 3r
Error: 3r is not a valid integer
Input greet times: 3
Enter debug mode
Greet 0: Hello farmer
Greet 1: Hello farmer
Greet 2: Hello farmer
Custom parameter is: magic
@click.option( )
還有更多用法,詳見options。
4 添加子命令
前面我們都是給main函數添加了很多參數,我們可以將@click.command()
修改爲@click.group(invoke_without_command=True)
。
添加參數invoke_without_command=True
是指主命令可以不指定子命令單獨執行。
此時我們要給main函數添加子命令,修飾符應該改爲main.command()
,以表示修飾的函數作爲main函數的子命令,子命令同樣可以擁有自己的參數。
示例如下:
@click.group(invoke_without_command=True)
@click.pass_context
def main(ctx):
if ctx.invoked_subcommand is None:
click.echo('I was invoked without subcommand')
else:
click.echo('I am about to invoke %s' % ctx.invoked_subcommand)
@main.command()
@click.argument('count')
def boo(count):
print('boo ' * count)
此時查看主命令和子命令的help:
# python3 click_demo.py --help
Usage: click_demo.py [OPTIONS] COMMAND [ARGS]...
Options:
--help Show this message and exit.
Commands:
boo
# python3 click_demo.py boo --help
I am about to invoke boo
Usage: click_demo.py boo [OPTIONS] COUNT
Options:
--help Show this message and exit.
可以看到主命令的幫助內容介紹了其子命令Commands
,包括boo
;boo
子命令的--help
會顯示其參數介紹。
子命令會是在main函數執行完以後執行,正常執行亦是如此:
# python3 click_demo.py
I was invoked without subcommand
# python3 click_demo.py boo 5
I am about to invoke boo
boo boo boo boo boo
詳細的@click.group()
使用方法詳見commands。