日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > python >内容正文

python

python命令行操作:Click包

發(fā)布時(shí)間:2024/1/8 python 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python命令行操作:Click包 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

0 前言

在Python開發(fā)和測試過程中主要有兩種模式可以選擇:腳本模式、命令行模式。在代碼的開發(fā)和調(diào)試過程中使用腳本模式還是很方便的,尤其接觸pycharm、eclipse這類強(qiáng)大的IDE,或者配合vs code這種綜合的文本編輯器。但是如果使用純文本編輯器,或者是在做整個(gè)系統(tǒng)開發(fā)時(shí),與其他模型進(jìn)行接口調(diào)用時(shí),命令行模式就顯得非常重要了。目前有很多熱門的命令行工具,本文會(huì)一一介紹一下,并且重點(diǎn)介紹一下最近發(fā)現(xiàn)的一款命令行神器Click。
這款包配合setuptools的end_points參數(shù)可以,在命令行直接執(zhí)行自定義的命令,而不需要使用python 腳本.py 參數(shù)這樣的格式。

1 Click簡介

Click 是 Flask 的團(tuán)隊(duì) pallets 開發(fā)的優(yōu)秀開源項(xiàng)目,它為命令行工具的開發(fā)封裝了大量方法,使開發(fā)者只需要專注于功能實(shí)現(xiàn)。恰好我最近在開發(fā)的一個(gè)小工具需要在命令行環(huán)境下操作,就寫個(gè)學(xué)習(xí)筆記。

2 Hello World

國際慣例,先來一段 “Hello World” 程序(假定已經(jīng)安裝了 Click 包)。

hello.py

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()

執(zhí)行結(jié)果為:

除此之外,Click 還悄悄地做了其他的工作,比如添加幫助選項(xiàng):

$ python hello.py --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.

3 函數(shù)變CLI

3.1 command

從上面的 “Hello World” 演示中可以看出,Click 是通過裝飾器來把一個(gè)函數(shù)方法裝飾成命令行接口的,這個(gè)裝飾器方法就是 @click.command()。

import click@click.command() def hello():click.echo('Hello World!')

@click.command() 裝飾器把 hello() 方法變成了 Command 對象,當(dāng)它被調(diào)用時(shí),就會(huì)執(zhí)行該實(shí)例內(nèi)的行為。而 --help 參數(shù)就是 Command 對象內(nèi)置的參數(shù)。

3.2 group

不同的 Command 實(shí)例可以關(guān)聯(lián)到 group 中。group 下綁定的命令就成為了它的子命令,參考下面的代碼:

@click.group() def cli():pass@click.command() def initdb():click.echo('Initialized the database')@click.command() def dropdb():click.echo('Dropped the database')cli.add_command(initdb) cli.add_command(dropdb) cli()

執(zhí)行結(jié)果為:

@click.group 裝飾器把方法裝飾為可以擁有多個(gè)子命令的 Group 對象。由 Group.add_command() 方法把 Command 對象關(guān)聯(lián)到 Group 對象。 也可以直接用 @Group.command 裝飾方法,會(huì)自動(dòng)把方法關(guān)聯(lián)到該 Group 對象下。

@click.group() def cli():pass@cli.command() def initdb():click.echo('Initialized the database')@cli.command() def dropdb():click.echo('Dropped the database') cli()

執(zhí)行結(jié)果為:

4 命令行參數(shù)介紹

命令行的參數(shù)功能是不可或缺的,Click 支持對 command 方法添加自定義的參數(shù),由 option() 和 argument() 裝飾器實(shí)現(xiàn)。

@click.command() @click.option('--count', default=1, help='number of greetings') @click.argument('name') def hello(count, name):for x in range(count):click.echo('Hello %s!' % name)

上面使用了自定義命令行參數(shù)的兩個(gè)裝飾器:@click.option() 和 @click.argument(),兩者有些許區(qū)別,使用場景也有所不同。
總體而言,argument() 裝飾器比 option() 功能簡單些。
option支持下面的特性:

  • 自動(dòng)提示缺失的輸入;
  • option 參數(shù)可以從環(huán)境變量中獲取,argument 參數(shù)則不行;
  • option 參數(shù)在 help 輸出中有完整的文檔,argument 則沒有;

而 argument 參數(shù)可以接受可變個(gè)數(shù)的參數(shù)值,而 option 參數(shù)只能接收固定個(gè)數(shù)的參數(shù)值(默認(rèn)是 1 個(gè))。
Click 可以設(shè)置不同的參數(shù)類型,簡單類型如 click.STRING,click.INT,click.FLOAT,click.BOOL。
命令行的參數(shù)名由 “-short_name” 和 “–long_name” 聲明,如果參數(shù)名既沒有以 “-” 開頭,也沒有以 “–” 開頭,那么這邊變量名會(huì)成為被裝飾方法的內(nèi)部變量,而非方法參數(shù)。

4.1 option參數(shù)

option 最基礎(chǔ)的用法就是簡單值變量,option 接收一個(gè)變量值,下面是一段示例代碼:

@click.command() @click.option('--n', default=1) def dots(n):click.echo('.' * n)

如果在命令行后面跟隨參數(shù) --n=2 就會(huì)輸出兩個(gè)點(diǎn),如果傳參數(shù),默認(rèn)輸出一個(gè)點(diǎn)。上面的代碼中,參數(shù)類型沒有顯示給出,但解釋器會(huì)認(rèn)為是 INT 型,因?yàn)槟J(rèn)值 1 是 int 值。 有些時(shí)候需要傳入多個(gè)值,可以理解為一個(gè) list,option 只支持固定長度的參數(shù)值,即設(shè)置后必須傳入,個(gè)數(shù)由 nargs 確定。

@click.command() @click.option('--pos', nargs=2, type=float) def findme(pos):click.echo('%s / %s' % pos)

findme --pos 2.0 3.0 輸出結(jié)果就是 2.0 / 3.0
既然可以傳入 list,那么 tuple 呢?Click 也是支持的:

@click.command() @click.option('--item', type=(unicode, int)) def putitem(item):click.echo('name=%s id=%d' % item)

這樣就傳入了一個(gè) tuple 變量,putitem --item peter 1338 得到的輸出就是 name=peter id=1338 上面沒有設(shè)置 nargs,因?yàn)?nargs 會(huì)自動(dòng)取 tuple 的長度值。因此上面的代碼實(shí)際上等同于:

@click.command() @click.option('--item', nargs=2, type=click.Tuple([unicode, int])) def putitem(item):click.echo('name=%s id=%d' % item)

option 還支持同一個(gè)參數(shù)多次使用,類似 git commit -m aa -m bb 中 -m 參數(shù)就傳入了 2 次。option 通過 multiple 標(biāo)識位來支持這一特性:

@click.command() @click.option('--message', '-m', multiple=True) def commit(message):click.echo('\n'.join(message))

有時(shí)候,命令行參數(shù)是固定的幾個(gè)值,這時(shí)就可以用到 Click.choice 類型來限定傳參的潛在值:

# choice @click.command() @click.option('--hash-type', type=click.Choice(['md5', 'sha1'])) def digest(hash_type):click.echo(hash_type)

當(dāng)上面的命令行程序參數(shù) --hash-type 不是 md5 或 sha1,就會(huì)輸出錯(cuò)誤提示,并且在 --help 提示中也會(huì)對 choice 選項(xiàng)有顯示。
既然支持 Choice,不難聯(lián)想到 Range,先看代碼:

# range @click.command() @click.option('--count', type=click.IntRange(0, 20, clamp=True)) @click.option('--digit', type=click.IntRange(0, 10)) def repeat(count, digit):click.echo(str(digit) * count)if __name__ == '__main__':repeat()

如果希望命令行程序能在我們錯(cuò)誤輸入或漏掉輸入的情況下,友好的提示用戶,就需要用到 Click 的 prompt 功能,看代碼:

# prompt @click.command() @click.option('--name', prompt=True) def hello(name):click.echo('Hello %s!' % name)

如果在執(zhí)行 hello 時(shí)沒有提供 –name 參數(shù),控制臺會(huì)提示用戶輸入該參數(shù)。也可以自定義控制臺的提示輸出,把 prompt 改為自定義內(nèi)容即可。如第一部分的hello world中的prompt設(shè)置為Your name。
對于類似賬戶密碼等參數(shù)的輸入,就要進(jìn)行隱藏顯示。option 的 hide_input 和 confirmation_promt 標(biāo)識就是用來控制密碼參數(shù)的輸入:

# password @click.command() @click.option('--password', prompt=True, hide_input=True,confirmation_prompt=True) def encrypt(password):click.echo('Encrypting password to %s' % password.encode('rot13'))

Click 把上面的操作進(jìn)一步封裝成裝飾器 click.password_option(),因此上面的代碼也可以簡化成:

# password @click.command() @click.password_option() def encrypt(password):click.echo('Encrypting password to %s' % password.encode('rot13'))

有的參數(shù)會(huì)改變命令行程序的執(zhí)行,比如 node 是進(jìn)入 Node 控制臺,而 node --verion 是輸出 node 的版本號。Click 提供 eager 標(biāo)識對參數(shù)名進(jìn)行標(biāo)記,攔截既定的命令行執(zhí)行流程,而是調(diào)用一個(gè)回調(diào)方法,執(zhí)行后直接退出。下面模擬 click.version_option() 的功能,實(shí)現(xiàn) --version 參數(shù)名輸出版本號:

# eager def print_version(ctx, param, value):if not value or ctx.resilient_parsing:returnclick.echo('Version 1.0')ctx.exit()@click.command() @click.option('--version', is_flag=True, callback=print_version,expose_value=False, is_eager=True) def hello():click.echo('Hello World!')if __name__ == '__main__':hello()

運(yùn)行結(jié)果:

對于類似刪除數(shù)據(jù)庫表這樣的危險(xiǎn)操作,Click 支持彈出確認(rèn)提示,–yes 標(biāo)識位置為 True 時(shí)會(huì)讓用戶再次確認(rèn):

# yes parameters def abort_if_false(ctx, param, value):if not value:ctx.abort()@click.command() @click.option('--yes', is_flag=True, callback=abort_if_false,expose_value=False,prompt='Are you sure you want to drop the db?') def dropdb():click.echo('Dropped all tables!')

測試運(yùn)行下:

$ dropdb Are you sure you want to drop the db? [y/N]: n Aborted! $ dropdb --yes Dropped all tables!

同樣的,Click 對次進(jìn)行了封裝,click.confirmation_option() 裝飾器實(shí)現(xiàn)了上述功能:

@click.command() @click.confirmation_option(prompt='Are you sure you want to drop the db?') def dropdb():click.echo('Dropped all tables!')

前面只講了默認(rèn)的參數(shù)前綴 – 和 -,Click 允許開發(fā)者自定義參數(shù)前綴(雖然嚴(yán)重不推薦)。

# other prefix @click.command() @click.option('+w/-w') def chmod(w):click.echo('writable=%s' % w)if __name__ == '__main__':chmod()

如果想要用 / 作為前綴,而且要像上面一樣采用布爾標(biāo)識,會(huì)產(chǎn)生沖突,因?yàn)椴紶枠?biāo)識也是用 /,這種情況下可以用 ; 代替布爾標(biāo)識的 /:

@click.command() @click.option('/debug;/no-debug') def log(debug):click.echo('debug=%s' % debug)if __name__ == '__main__':log()

4.2 argument 參數(shù)

Argument 的作用類似 Option,但沒有 Option 那么全面的功能。

和 Option 一樣,Argument 最基礎(chǔ)的應(yīng)用就是傳遞一個(gè)簡單變量值:

@click.command() @click.argument('filename') def touch(filename):click.echo(filename)

命令行后跟的參數(shù)值被賦值給參數(shù)名 filename。

另一個(gè)用的比較廣泛的是可變參數(shù),也是由 nargs 來確定參數(shù)個(gè)數(shù),變量值會(huì)以 tuple 的形式傳入函數(shù):

@click.command() @click.argument('src', nargs=-1) #-1表示可以接受不確定數(shù)量的參數(shù) @click.argument('dst', nargs=1) def copy(src, dst):for fn in src:click.echo('move %s to folder %s' % (fn, dst))

運(yùn)行程序:

$ copy foo.txt bar.txt my_folder move foo.txt to folder my_folder move bar.txt to folder my_folder

Click 支持通過文件名參數(shù)對文件進(jìn)行操作,click.File() 裝飾器就是處理這種操作的,尤其是在類 Unix 系統(tǒng)下,它支持以 - 符號作為標(biāo)準(zhǔn)輸入/輸出。

# File import click @click.command() @click.argument('input', type=click.File('rb')) @click.argument('output', type=click.File('wb')) def inout(input, output):chunk = input.readline()output.write(chunk)if __name__ == '__main__':inout()

運(yùn)行程序,將文本寫進(jìn)文件


經(jīng)過試驗(yàn)option好像不支持這種文件對象參數(shù)。

如果參數(shù)值只是想做為文件名而已呢,很簡單,將 type 指定為 click.Path():

@click.command() @click.argument('f', type=click.Path(exists=True)) def touch(f):click.echo(click.format_filename(f))

5 打包跨平臺可執(zhí)行程序

通過 Click 編寫了簡單的命令行方法后,還需要把 .py 文件轉(zhuǎn)換成可以在控制臺里運(yùn)行的命令行程序。最簡單的辦法就是在文件末尾加上如下代碼:

if __name__ == '__main__':command_name()

Click 支持使用 setuptools 來更好的實(shí)現(xiàn)命令行程序打包,把源碼文件打包成系統(tǒng)中的可執(zhí)行程序,并且不限平臺。一般我們會(huì)在源碼根目錄下創(chuàng)建 setup.py 腳本,先看一段簡單的打包代碼:
setup.py

from setuptools import setupsetup(name='hello',version='0.1',py_modules=['hello'],install_requires=['Click',],entry_points='''[console_scripts]hello=hello:cli''', )

留意 entry_points 字段,在 console_scripts 下,每一行都是一個(gè)控制臺腳本,等號左邊的的是腳本的名稱,右邊的是 Click 命令的導(dǎo)入路徑。
我們使用上面的打包程序,對下面的代碼進(jìn)行打包:

# hello.py import click@click.group() def cli():pass@cli.command() def initdb():click.echo('Initialized the database')@cli.command() def dropdb():click.echo('Dropped the database') cli()

打包命令:

然后進(jìn)行安裝和運(yùn)行:

有關(guān)python打包和運(yùn)行的詳細(xì)內(nèi)容看考博客:python程序的打包和安裝

原文鏈接:Python Click 學(xué)習(xí)筆記

總結(jié)

以上是生活随笔為你收集整理的python命令行操作:Click包的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。