鍍金池/ 教程/ Python/ Click
基礎(chǔ)
itertools
HTTP 服務(wù)
hashlib
閉包
文件和目錄
單元測試
使用 @property
標(biāo)準(zhǔn)模塊
陌生的 metaclass
Base64
進(jìn)程、線程和協(xié)程
讀寫二進(jìn)制文件
匿名函數(shù)
輸入和輸出
Click
元組
字符編碼
partial 函數(shù)
參考資料
collections
協(xié)程
類和實(shí)例
Python 之旅
定制類和魔法方法
常用數(shù)據(jù)類型
繼承和多態(tài)
ThreadLocal
HTTP 協(xié)議簡介
Requests 庫的使用
讀寫文本文件
列表
os 模塊
迭代器 (Iterator)
正則表達(dá)式
集合
上下文管理器
異常處理
你不知道的 super
定義函數(shù)
datetime
資源推薦
字典
slots 魔法
hmac
第三方模塊
進(jìn)程
類方法和靜態(tài)方法
函數(shù)參數(shù)
高階函數(shù)
函數(shù)
re 模塊
高級特性
線程
argparse
生成器
結(jié)束語
字符串
map/reduce/filter
函數(shù)式編程
Celery
裝飾器

Click

ClickFlask 的開發(fā)團(tuán)隊(duì) Pallets 的另一款開源項(xiàng)目,它是用于快速創(chuàng)建命令行的第三方模塊。我們知道,Python 內(nèi)置了一個(gè) Argparse 的標(biāo)準(zhǔn)庫用于創(chuàng)建命令行,但使用起來有些繁瑣,Click 相比于 Argparse,就好比 requests 相比于 urllib

快速使用

Click 的使用大致有兩個(gè)步驟:

  1. 使用 @click.command() 裝飾一個(gè)函數(shù),使之成為命令行接口;
  2. 使用 @click.option() 等裝飾函數(shù),為其添加命令行選項(xiàng)等。

它的一種典型使用形式如下:

import click

@click.command()
@click.option('--param', default=default_value, help='description')
def func(param):
    pass

下面,讓我們看一下官方文檔的入門例子:

import click

@click.command()
@click.option('--count', default=1, help='Number of greetings.')
@click.option('--name', prompt='Your name', help='The person to greet.')
def hello(count, name):
    """Simple program that greets NAME for a total of COUNT times."""
    for x in range(count):
        click.echo('Hello %s!' % name)

if __name__ == '__main__':
    hello()

在上面的例子中,函數(shù) hello 有兩個(gè)參數(shù):count 和 name,它們的值從命令行中獲取。

  • @click.command() 使函數(shù) hello 成為命令行接口;
  • @click.option 的第一個(gè)參數(shù)指定了命令行選項(xiàng)的名稱,不難猜到,count 的默認(rèn)值是 1,name 的值從輸入獲??;
  • 使用 click.echo 進(jìn)行輸出是為了獲得更好的兼容性,因?yàn)?print 在 Python2 和 Python3 的用法有些差別。

看看執(zhí)行情況:

$ python hello.py
Your name: Ethan           # 這里會(huì)顯示 'Your name: '(對應(yīng)代碼中的 prompt),接受用戶輸入
Hello Ethan!

$ python hello.py --help   # click 幫我們自動(dòng)生成了 `--help` 用法
Usage: hello.py [OPTIONS]

  Simple program that greets NAME for a total of COUNT times.

Options:
  --count INTEGER  Number of greetings.
  --name TEXT      The person to greet.
  --help           Show this message and exit.

$ python hello.py --count 3 --name Ethan    # 指定 count 和 name 的值
Hello Ethan!
Hello Ethan!
Hello Ethan!

$ python hello.py --count=3 --name=Ethan    # 也可以使用 `=`,和上面等價(jià)
Hello Ethan!
Hello Ethan!
Hello Ethan!

$ python hello.py --name=Ethan              # 沒有指定 count,默認(rèn)值是 1
Hello Ethan!

click.option

option 最基本的用法就是通過指定命令行選項(xiàng)的名稱,從命令行讀取參數(shù)值,再將其傳遞給函數(shù)。在上面的例子,我們看到,除了設(shè)置命令行選項(xiàng)的名稱,我們還會(huì)指定默認(rèn)值,help 說明等,option 常用的設(shè)置參數(shù)如下:

  • default: 設(shè)置命令行參數(shù)的默認(rèn)值
  • help: 參數(shù)說明
  • type: 參數(shù)類型,可以是 string, int, float 等
  • prompt: 當(dāng)在命令行中沒有輸入相應(yīng)的參數(shù)時(shí),會(huì)根據(jù) prompt 提示用戶輸入
  • nargs: 指定命令行參數(shù)接收的值的個(gè)數(shù)

下面,我們再看看相關(guān)的例子。

指定 type

我們可以使用 type 來指定參數(shù)類型:

import click

@click.command()
@click.option('--rate', type=float, help='rate')   # 指定 rate 是 float 類型
def show(rate):
    click.echo('rate: %s' % rate)

if __name__ == '__main__':
    show()

執(zhí)行情況:

$ python click_type.py --rate 1
rate: 1.0
$ python click_type.py --rate 0.66
rate: 0.66

可選值

在某些情況下,一個(gè)參數(shù)的值只能是某些可選的值,如果用戶輸入了其他值,我們應(yīng)該提示用戶輸入正確的值。在這種情況下,我們可以通過 click.Choice() 來限定:

import click

@click.command()
@click.option('--gender', type=click.Choice(['man', 'woman']))    # 限定值
def choose(gender):
    click.echo('gender: %s' % gender)

if __name__ == '__main__':
    choose()

執(zhí)行情況:

$ python click_choice.py --gender boy
Usage: click_choice.py [OPTIONS]

Error: Invalid value for "--gender": invalid choice: boy. (choose from man, woman)

$ python click_choice.py --gender man
gender: man

多值參數(shù)

有時(shí),一個(gè)參數(shù)需要接收多個(gè)值。option 支持設(shè)置固定長度的參數(shù)值,通過 nargs 指定。

看看例子就明白了:

import click

@click.command()
@click.option('--center', nargs=2, type=float, help='center of the circle')
@click.option('--radius', type=float, help='radius of the circle')
def circle(center, radius):
    click.echo('center: %s, radius: %s' % (center, radius))

if __name__ == '__main__':
    circle()

在上面的例子中,option 指定了兩個(gè)參數(shù):center 和 radius,其中,center 表示二維平面上一個(gè)圓的圓心坐標(biāo),接收兩個(gè)值,以元組的形式將值傳遞給函數(shù),而 radius 表示圓的半徑。

執(zhí)行情況:

$ python click_multi_values.py --center 3 4 --radius 10
center: (3.0, 4.0), radius: 10.0

$ python click_multi_values.py --center 3 4 5 --radius 10
Usage: click_multi_values.py [OPTIONS]

Error: Got unexpected extra argument (5)

輸入密碼

有時(shí),在輸入密碼的時(shí)候,我們希望能隱藏顯示。option 提供了兩個(gè)參數(shù)來設(shè)置密碼的輸入:hide_input 和 confirmation_promt,其中,hide_input 用于隱藏輸入,confirmation_promt 用于重復(fù)輸入。

看看例子:

import click

@click.command()
@click.option('--password', prompt=True, hide_input=True, confirmation_prompt=True)
def input_password(password):
    click.echo('password: %s' % password)

if __name__ == '__main__':
    input_password()

執(zhí)行情況:

$ python click_password.py
Password:                         # 不會(huì)顯示密碼
Repeat for confirmation:          # 重復(fù)一遍
password: 666666

由于上面的寫法有點(diǎn)繁瑣,click 也提供了一種快捷的方式,通過使用 @click.password_option(),上面的代碼可以簡寫成:

import click

@click.command()
@click.password_option()
def input_password(password):
    click.echo('password: %s' % password)

if __name__ == '__main__':
    input_password()

改變命令行程序的執(zhí)行

有些參數(shù)會(huì)改變命令行程序的執(zhí)行,比如在終端輸入 python 是進(jìn)入 python 控制臺(tái),而輸入 python --version 是打印 python 版本。Click 提供 eager 標(biāo)識(shí)對參數(shù)名進(jìn)行標(biāo)識(shí),如果輸入該參數(shù),則會(huì)攔截既定的命令行執(zhí)行流程,跳轉(zhuǎn)去執(zhí)行一個(gè)回調(diào)函數(shù)。

讓我們看看例子:

import click

def print_version(ctx, param, value):
    if not value or ctx.resilient_parsing:
        return
    click.echo('Version 1.0')
    ctx.exit()

@click.command()
@click.option('--version', is_flag=True, callback=print_version,
              expose_value=False, is_eager=True)
@click.option('--name', default='Ethan', help='name')
def hello(name):
    click.echo('Hello %s!' % name)

if __name__ == '__main__':
    hello()

其中:

  • is_eager=True 表明該命令行選項(xiàng)優(yōu)先級高于其他選項(xiàng);
  • expose_value=False 表示如果沒有輸入該命令行選項(xiàng),會(huì)執(zhí)行既定的命令行流程;
  • callback 指定了輸入該命令行選項(xiàng)時(shí),要跳轉(zhuǎn)執(zhí)行的函數(shù);

執(zhí)行情況:

$ python click_eager.py
Hello Ethan!

$ python click_eager.py --version                   # 攔截既定的命令行執(zhí)行流程
Version 1.0

$ python click_eager.py --name Michael
Hello Michael!

$ python click_eager.py --version --name Ethan      # 忽略 name 選項(xiàng)
Version 1.0

click.argument

我們除了使用 @click.option 來添加可選參數(shù),還會(huì)經(jīng)常使用 @click.argument 來添加固定參數(shù)。它的使用和 option 類似,但支持的功能比 option 少。

入門使用

下面是一個(gè)簡單的例子:

import click

@click.command()
@click.argument('coordinates')
def show(coordinates):
    click.echo('coordinates: %s' % coordinates)

if __name__ == '__main__':
    show()

看看執(zhí)行情況:

$ python click_argument.py                     # 錯(cuò)誤,缺少參數(shù) coordinates
Usage: click_argument.py [OPTIONS] COORDINATES

Error: Missing argument "coordinates".

$ python click_argument.py --help              # argument 指定的參數(shù)在 help 中沒有顯示
Usage: click_argument.py [OPTIONS] COORDINATES

Options:
  --help  Show this message and exit.

$ python click_argument.py --coordinates 10    # 錯(cuò)誤用法,這是 option 參數(shù)的用法
Error: no such option: --coordinates

$ python click_argument.py 10                  # 正確,直接輸入值即可
coordinates: 10

多個(gè) argument

我們再來看看多個(gè) argument 的例子:

import click

@click.command()
@click.argument('x')
@click.argument('y')
@click.argument('z')
def show(x, y, z):
    click.echo('x: %s, y: %s, z:%s' % (x, y, z))

if __name__ == '__main__':
    show()

執(zhí)行情況:

$ python click_argument.py 10 20 30
x: 10, y: 20, z:30

$ python click_argument.py 10
Usage: click_argument.py [OPTIONS] X Y Z

Error: Missing argument "y".

$ python click_argument.py 10 20
Usage: click_argument.py [OPTIONS] X Y Z

Error: Missing argument "z".

$ python click_argument.py 10 20 30 40
Usage: click_argument.py [OPTIONS] X Y Z

Error: Got unexpected extra argument (40)

不定參數(shù)

argument 還有另外一種常見的用法,就是接收不定量的參數(shù),讓我們看看例子:

import click

@click.command()
@click.argument('src', nargs=-1)
@click.argument('dst', nargs=1)
def move(src, dst):
    click.echo('move %s to %s' % (src, dst))

if __name__ == '__main__':
    move()

其中,nargs=-1 表明參數(shù) src 接收不定量的參數(shù)值,參數(shù)值會(huì)以 tuple 的形式傳入函數(shù)。如果 nargs 大于等于 1,表示接收 nargs 個(gè)參數(shù)值,上面的例子中,dst 接收一個(gè)參數(shù)值。

讓我們看看執(zhí)行情況:

$ python click_argument.py file1 trash    # src=('file1',)  dst='trash'
move (u'file1',) to trash

$ python click_argument.py file1 file2 file3 trash   # src=('file1', 'file2', 'file3')  dst='trash'
move (u'file1', u'file2', u'file3') to trash

彩色輸出

在前面的例子中,我們使用 click.echo 進(jìn)行輸出,如果配合 colorama 這個(gè)模塊,我們可以使用 click.secho 進(jìn)行彩色輸出,在使用之前,使用 pip 安裝 colorama:

$ pip install colorama

看看例子:

import click

@click.command()
@click.option('--name', help='The person to greet.')
def hello(name):
    click.secho('Hello %s!' % name, fg='red', underline=True)
    click.secho('Hello %s!' % name, fg='yellow', bg='black')

if __name__ == '__main__':
    hello()

其中:

  • fg 表示前景顏色(即字體顏色),可選值有:BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE 等;
  • bg 表示背景顏色,可選值有:BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE 等;
  • underline 表示下劃線,可選的樣式還有:dim=True,bold=True 等;

小結(jié)

  • 使用 click.command() 裝飾一個(gè)函數(shù),使其成為命令行接口。
  • 使用 click.option() 添加可選參數(shù),支持設(shè)置固定長度的參數(shù)值。
  • 使用 click.argument() 添加固定參數(shù),支持設(shè)置不定長度的參數(shù)值。

參考資料

上一篇:字典下一篇:函數(shù)式編程