開(kāi)發(fā)命令行工具的十個(gè) Click 庫(kù)高級(jí)參數(shù)
今天就來(lái)跟大家聊聊,如何用Click庫(kù)開(kāi)發(fā)命令行工具的10個(gè)高級(jí)參數(shù)。一步步來(lái),咱們先從簡(jiǎn)單的開(kāi)始,再到更高級(jí)的功能。
1. 定義基本命令
首先,使用Click庫(kù),我們要定義一個(gè)最基本的命令。這是一個(gè)入門的例子。
# 導(dǎo)入click庫(kù)
import click
# 定義一個(gè)點(diǎn)擊裝飾器
@click.command()
# 定義函數(shù)處理程序邏輯
def hello():
"""簡(jiǎn)單的命令,輸出Hello"""
click.echo("Hello!")
# 主函數(shù)調(diào)用
if __name__ == '__main__':
hello()
運(yùn)行輸出:
Hello!
這里 click.echo() 是Click推薦使用的打印方式。它比標(biāo)準(zhǔn) print 更加靈活和強(qiáng)大,尤其是涉及到Unicode或不同平臺(tái)間的兼容性問(wèn)題時(shí)。
2. 添加簡(jiǎn)單參數(shù)
現(xiàn)在我們往這個(gè)簡(jiǎn)單的命令中加入一個(gè)可以輸入的名字參數(shù)。
import click
@click.command()
@click.argument('name') # 使用參數(shù)
def greet(name):
"""接收name參數(shù),打印個(gè)性化問(wèn)候"""
click.echo(f"Hello, {name}!")
if __name__ == '__main__':
greet()
示例運(yùn)行:
$ python app.py Alice
Hello, Alice!
這一步中,@click.argument('name') 這句代碼,允許命令行后面直接添加參數(shù)。
3. 帶類型的選項(xiàng)
我們可以給我們的命令行加入更多選擇項(xiàng),并且指定這些項(xiàng)應(yīng)該是什么樣的數(shù)據(jù)類型。
import click
@click.command()
@click.option('--age', type=int, help="Your age in years.") # 聲明age選項(xiàng),要求為int類型
def display(age):
"""顯示年齡"""
click.echo(f"Your entered age is: {age}")
if __name__ == '__main__':
display()
運(yùn)行:
$ python app.py --age 26
Your entered age is: 26
這樣,通過(guò) --age 參數(shù)指定用戶的年齡,并在運(yùn)行時(shí)得到反饋。
4. 默認(rèn)值與幫助文本
接著,讓我們看看如何為選項(xiàng)設(shè)置默認(rèn)值和幫助信息,這樣可以讓用戶更容易地了解命令該如何使用。
import click
@click.command()
@click.option('--temperature', default=20, help="Room temperature in degrees Celsius.")
def adjust_temp(temperature):
"""調(diào)整溫度設(shè)置"""
click.echo(f"The current room temperature is set to: {temperature}°C")
if __name__ == '__main__':
adjust_temp()
輸出結(jié)果(無(wú)指定值):
The current room temperature is set to: 20°C
5. 強(qiáng)制用戶確認(rèn)
有些操作可能有破壞性,比如刪除文件之類的,那就可以加上用戶必須的交互確認(rèn)了。
import click
@click.command()
@click.confirmation_option(prompt='Are you sure you want to proceed?')
def danger():
"""需要用戶確認(rèn)的操作"""
click.echo("Action performed!")
if __name__ == '__main__':
danger()
在這個(gè)腳本執(zhí)行時(shí),如果未輸入 yes 或 y,則該命令不會(huì)生效。
6. 接受多種輸入模式的值
如果你有一些選項(xiàng)是可以接受多個(gè)值的,比如說(shuō)顏色列表,也可以很方便實(shí)現(xiàn)。
import click
@click.command()
@click.option('--colors', multiple=True, help="List of colors")
def show_colors(colors):
"""展示所有提供的顏色"""
for color in colors:
click.echo(f"You chose the color: {color}")
if __name__ == '__main__':
show_colors()
運(yùn)行示例:
$ python app.py --colors red --colors green
You chose the color: red
You chose the color: green
7. 文件讀取和寫(xiě)入支持
很多時(shí)候命令行需要處理文件輸入或者輸出。
import click
@click.command()
@click.argument('input_file', type=click.File('r'))
@click.argument('output_file', type=click.File('w'))
def copy(input_file, output_file):
"""拷貝內(nèi)容至另一文件"""
output_file.write(input_file.read())
click.echo('File copied successfully!')
if __name__ == '__main__':
copy()
這個(gè)腳本將讀取第一個(gè)文件的內(nèi)容,將其拷貝到另一個(gè)文件。
8. 組合多命令
有時(shí)候,一個(gè)命令行工具需要很多子命令。比如 git add, git commit 等等。
import click
@click.group()
def cli():
"""主組"""
@cli.command()
def initdb():
click.echo('Initialized the database')
@cli.command()
def dropdb():
click.echo('Dropped the database')
if __name__ == '__main__':
cli()
在這里使用 @click.group() 可以讓我們輕松定義一組子命令。
9. 回調(diào)機(jī)制與驗(yàn)證
如果需要對(duì)用戶提供信息進(jìn)行驗(yàn)證,也可以很容易完成:
import click
def validate_age(ctx, param, value):
try:
if value < 0:
raise ValueError
return value
except ValueError:
raise click.BadParameter('Age must be a non-negative integer.')
@click.command()
@click.option('--age', callback=validate_age, type=int)
def process(age):
"""驗(yàn)證年齡正確性"""
click.echo(f"Processed your valid age: {age}")
if __name__ == '__main__':
process()
當(dāng)年齡不是正數(shù)或非整數(shù)時(shí)候?qū)?huì)提示用戶錯(cuò)誤信息。
10. 實(shí)際場(chǎng)景 - 文件查找器
下面是一個(gè)綜合的小案例,創(chuàng)建一個(gè)能夠遞歸搜索特定目錄下符合某種擴(kuò)展名文件的應(yīng)用程序:
import os
import click
def find_files(dir, ext):
"""實(shí)際查找文件方法"""
results = []
for dirpath, dirnames, filenames in os.walk(dir):
for filename in filenames:
if filename.endswith(ext):
results.append(os.path.join(dirpath, filename))
return results
@click.command()
@click.option('-d', '--dir', required=True, type=click.Path(exists=True), help='Directory to search.')
@click.option('-e', '--ext', required=True, help='File extension.')
def finder(dir, ext):
"""命令行應(yīng)用:尋找擴(kuò)展名為EXT的文件"""
files = find_files(dir, ext)
if not files:
click.echo('No matching files found.')
else:
for file in files:
click.echo(file)
if __name__ == '__main__':
finder()
這段程序會(huì)基于給出的目錄和擴(kuò)展名去尋找相關(guān)聯(lián)的文件,并把它們打印出來(lái)。
總結(jié)
在這篇文章里,我們介紹了利用Click構(gòu)建命令行工具時(shí)可以運(yùn)用到的十個(gè)高級(jí)特性。這些包括但不限于定義基礎(chǔ)命令,參數(shù)管理,選項(xiàng)配置如指定類型、提供默認(rèn)值、強(qiáng)制確認(rèn)、處理多重輸入以及文件輸入輸出功能。還涉及組合型子命令的設(shè)計(jì)、數(shù)據(jù)校驗(yàn)回調(diào),最后結(jié)合所學(xué)到的知識(shí)構(gòu)建了一個(gè)實(shí)用的小型遞歸文件搜素器示例。