涉及的示例代碼和歷史文章,已同步更新到 HelloGitHub-Team 倉庫python
在前面三篇文章中,咱們介紹了 click
中的參數、選項和命令,本文將介紹 click
錦上添花的功能,以幫助咱們更加輕鬆地打造一個更增強大的命令行程序。git
本系列文章默認使用 Python 3 做爲解釋器進行講解。
若你仍在使用 Python 2,請注意二者之間語法和庫的使用差別哦~
複製代碼
Bash 補全是 click
提供的一個很是便捷和強大的功能,這是它比 argpase
和 docopt
強大的一個表現。github
在命令行程序正確安裝後,Bash 補全才可使用。而如何安裝能夠參考 setup 集成。Click 目前僅支持 Bash 和 Zsh 的補全。shell
一般來講,Bash 補全支持對子命令、選項、以及選項或參數值得補全。好比:編程
$ repo <TAB><TAB>
clone commit copy delete setuser
$ repo clone -<TAB><TAB>
--deep --help --rev --shallow -r
複製代碼
此外,click
還支持自定義補全,這在動態生成補全場景中頗有用,使用 autocompletion
參數。autocompletion
須要指定爲一個回調函數,而且返回字符串的列表。此函數接受三個參數:api
ctx
—— 當前的 click 上下文args
傳入的參數列表incomplete
正在補全的詞這裏有一個根據環境變量動態生成補全的示例:瀏覽器
import os
def get_env_vars(ctx, args, incomplete):
return [k for k in os.environ.keys() if incomplete in k]
@click.command()
@click.argument("envvar", type=click.STRING, autocompletion=get_env_vars)
def cmd1(envvar):
click.echo('Environment variable: %s' % envvar)
click.echo('Value: %s' % os.environ[envvar])
複製代碼
在 ZSH
中,還支持補全幫助信息。只需將 autocompletion
回調函數中返回的字符串列表中的字符串改成二元元組,第一個元素是補全內容,第二個元素是幫助信息。bash
這裏有一個顏色補全的示例:app
import os
def get_colors(ctx, args, incomplete):
colors = [('red', 'help string for the color red'),
('blue', 'help string for the color blue'),
('green', 'help string for the color green')]
return [c for c in colors if incomplete in c[0]]
@click.command()
@click.argument("color", type=click.STRING, autocompletion=get_colors)
def cmd1(color):
click.echo('Chosen color is %s' % color)
複製代碼
要激活 Bash 的補全功能,就須要告訴它你的命令行程序有補全的能力。一般經過一個神奇的環境變量 _<PROG_NAME>_COMPLETE
來告知,其中 <PROG_NAME>
是大寫下劃線形式的程序名稱。less
好比有一個命令行程序叫作 foo-bar
,那麼對應的環境變量名稱爲 _FOO_BAR_COMPLETE
,而後在 .bashrc
中使用 source
導出便可:
eval "$(_FOO_BAR_COMPLETE=source foo-bar)"
複製代碼
或者在 .zshrc
中使用:
eval "$(_FOO_BAR_COMPLETE=source_zsh foo-bar)"
複製代碼
不過上面的方式老是在命令行程序啓動時調用,這可能在有多個程序時減慢 shell 激活的速度。另外一種方式是把命令放在文件中,就像這樣:
# 針對 Bash
_FOO_BAR_COMPLETE=source foo-bar > foo-bar-complete.sh
# 針對 ZSH
_FOO_BAR_COMPLETE=source_zsh foo-bar > foo-bar-complete.sh
複製代碼
而後把腳本文件路徑加到 .bashrc
或 .zshrc
中:
. /path/to/foo-bar-complete.sh
複製代碼
echo() 函數能夠說是最有用的實用工具了。它和 Python 的 print
相似,主要的區別在於它同時在 Python 2 和 3 中生效,可以智能地檢測未配置正確的輸出流,且幾乎不會失敗(除了 Python 3 中的少數限制。)
echo
即支持 unicode,也支持二級制數據,如:
import click
click.echo('Hello World!')
click.echo(b'\xe2\x98\x83', nl=False) # nl=False 表示不輸出換行符
複製代碼
有些時候你可能但願輸出是有顏色的,這尤爲在輸出錯誤信息時有用,而 click
在這方面支持的很好。
首先,你須要安裝 colorama
:
pip install colorama
複製代碼
而後,就可使用 style() 函數來指定顏色:
import click
click.echo(click.style('Hello World!', fg='green'))
click.echo(click.style('Some more text', bg='blue', fg='white'))
click.echo(click.style('ATTENTION', blink=True, bold=True))
複製代碼
click
還提供了更加簡便的函數 secho,它就是 echo
和 style
的組合:
click.secho('Hello World!', fg='green')
click.secho('Some more text', bg='blue', fg='white')
click.secho('ATTENTION', blink=True, bold=True)
複製代碼
有些時候,命令行程序會輸出長文本,但你但願能讓用戶盤也瀏覽。使用 echo_via_pager() 函數就能夠輕鬆作到。
例如:
def less():
click.echo_via_pager('\n'.join('Line %d' % idx
for idx in range(200)))
複製代碼
若是輸出的文本特別大,處於性能的考慮,但願翻頁時生成對應內容,那麼就可使用生成器:
def _generate_output():
for idx in range(50000):
yield "Line %d\n" % idx
@click.command()
def less():
click.echo_via_pager(_generate_output())
複製代碼
使用 clear() 能夠輕鬆清除屏幕內容:
import click
click.clear()
複製代碼
一般狀況下,使用內建函數 input
或 raw_input
得到的輸入是用戶輸出一段字符而後回車獲得的。但在有些場景下,你可能想在用戶輸入單個字符時就能獲取到而且作必定的處理,這個時候 getchar() 就派上了用場。
好比,根據輸入的 y
或 n
作特定處理:
import click
click.echo('Continue? [yn] ', nl=False)
c = click.getchar()
click.echo()
if c == 'y':
click.echo('We will go on')
elif c == 'n':
click.echo('Abort!')
else:
click.echo('Invalid input :(')
複製代碼
在 Windows 的 cmd 中咱們常常看到當執行完一個命令後,提示按下任意鍵退出。經過使用 pause() 能夠實現暫停直至用戶按下任意鍵:
import click
click.pause()
複製代碼
經過 edit() 能夠自動啓動編輯器。這在須要用戶輸入多行內容時十分有用。
在下面的示例中,會啓動默認的文本編輯器,並在裏面輸入一段話:
import click
def get_commit_message():
MARKER = '# Everything below is ignored\n'
message = click.edit('\n\n' + MARKER)
if message is not None:
return message.split(MARKER, 1)[0].rstrip('\n')
複製代碼
edit()
函數還支持打開特定文件,好比:
import click
click.edit(filename='/etc/passwd')
複製代碼
經過 launch 能夠打開 URL 或文件類型所關聯的默認應用程序。若是設置 locate=True
,則能夠啓動文件管理器並自動選中特定文件。
示例:
# 打開瀏覽器,訪問 URL
click.launch("https://click.palletsprojects.com/")
# 使用默認應用程序打開 txt 文件
click.launch("/my/downloaded/file.txt")
# 打開文件管理器,並自動選中 file.txt
click.launch("/my/downloaded/file.txt", locate=True)
複製代碼
click
內置了 progressbar() 函數來方便地顯示進度條。
它的用法也很簡單,假定你有一個要處理的可迭代對象,處理完每一項就要輸出一下進度,那麼就有兩種用法。
用法一:使用 progressbar
構造出 bar
對象,迭代 bar
對象來自動告知進度:
import time
import click
all_the_users_to_process = ['a', 'b', 'c']
def modify_the_user(user):
time.sleep(0.5)
with click.progressbar(all_the_users_to_process) as bar:
for user in bar:
modify_the_user(user)
複製代碼
用法二:使用 progressbar
構造出 bar
對象,迭代原始可迭代對象,並不斷向 bar
更新進度:
import time
import click
all_the_users_to_process = ['a', 'b', 'c']
def modify_the_user(user):
time.sleep(0.5)
with click.progressbar(all_the_users_to_process) as bar:
for user in enumerate(all_the_users_to_process):
modify_the_user(user)
bar.update(1)
複製代碼
click
提供了很是多的加強型功能,本文着重介紹了它的 Bash 補全和十多個實用工具,這會讓你在實現命令行的過程當中如虎添翼。此外,click
還提供了諸如命令別名、參數修改、標準化令牌、調用其餘命令、回調順序等諸多高級模式 以應對更加複雜或特定的場景,咱們就再也不深刻介紹。
click
的介紹就告一段落,它將會是你編寫命令行程序的一大利器。在下一篇文章中,咱們依然會經過實現一個簡單的 git
程序來進行 click
的實戰。
抽獎活動:HG 聯合掘金社區舉辦的抽獎活動,獎品爲掘金贊助的該社區周邊:各類大禮包、新款衛衣。獎品共計 10 份,獎品多多。抽獎絕緣體的小夥伴能夠試一試,這多是你離中獎最近的一次。
『講解開源項目系列』——讓對開源項目感興趣的人再也不畏懼、讓開源項目的發起者再也不孤單。跟着咱們的文章,你會發現編程的樂趣、使用和發現參與開源項目如此簡單。歡迎留言聯繫咱們、加入咱們,讓更多人愛上開源、貢獻開源~