Python命令行工具-Click基礎

通過命令行運行腳本,設置合理的命令或者參數,可以讓腳本使用更加友好,避免頻繁修改源文件中的hard code導致的效率低下問題。
同時,這是也是踐行python的理念,讓程序變得更加Pythonic!更酷!

一 介紹

開發過程中我們可能需要讓我們的程序接受一些參數,以便執行不同的功能,而不需要修改代碼。
爲了實現這個功能,我們可以自己解析main函數的參數列表,也可以使用一些命令行工具。

命令行工具有很多,比如argparsefiredocopt,當然,包括click,不同工具有不同的“屬性”,選擇最合適自己習慣的一款即可。

命令行常用的參數類型:

  • 參數,必須要設定的值,以便程序能夠運行,比如find命令必須指定路徑
  • 選項,可選的參數,可以是各種類型,開關,數值,區間等等,比如ls命令可以指定路徑,否則默認是當前路徑
  • 子命令,給主命令添加子命令,同樣可以擁有各種參數,類似git configconfig就是git支持的子命令,config也有自己的參數

二 安裝

使用pip3安裝click:

pip3 install --user click

--user表示安裝到用戶目錄,更多時候都建議使用這個選項,可以避免一些權限問題。

三 使用

使用Click的一般步驟爲:

  1. 使用@click.command()裝飾指定函數,使之成爲命令行接口;
  2. 使用@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( )指定必備參數,以下是幾種常用的方法:

  1. 指定參數縮寫、完整名稱、自定義解析後的變量名、設置默認值和參數解釋:

    @click.option('-p', '--param-name', 'custom_param_name', default='magic', help='Parameter introduce.')
    
  2. 只指定完整參數名(對應變量名將按約定方式命名),指定參數類型(默認爲str),未指定參數時提示用戶輸入:

    @click.option('--count', type=int, prompt='Input greet times', help='The times to greet.')
    
  3. 設定一個開關標識位,不接受參數值(這是一個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.

此時參數已經變得豐富了,此時:

  1. 使用時必須指定參數USER_NAME
  2. 可以通過-p或者--param-name指定該參數的值,默認類型爲字符串;
  3. 可以通過--count=3或者--count 3指定問候語打印次數爲3次,類型爲整型;如果沒有指定,則會提示用戶輸入,並自動轉換爲整型;如果輸入的字符串不能轉換爲整數,則會提示再次輸入;
  4. 如果指定-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,包括booboo子命令的--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

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