當(dāng)前位置:首頁 > > HelloGitHub

一、前言

在前面五篇介紹 click的文章中,我們?nèi)媪私饬?click的強(qiáng)大能力。按照慣例,我們要像使用 argparse和 docopt一樣使用 click來實(shí)現(xiàn) git 命令。

本文的關(guān)注點(diǎn)并不在 git的各種命令是如何實(shí)現(xiàn)的,而是怎么使用 click去打造一個實(shí)用命令行程序,代碼結(jié)構(gòu)是怎樣的。因此,和 git相關(guān)的操作,將會使用 gitpython庫來簡單實(shí)現(xiàn)。

為了讓沒讀過 使用 xxx 實(shí)現(xiàn) git 命令(xxx指 argparse和 docopt) 的小伙伴也能讀明白本文,我們?nèi)詴?git常用命令和 gitpython做一個簡單介紹。

本系列文章默認(rèn)使用 Python 3 作為解釋器進(jìn)行講解。
若你仍在使用 Python 2,請注意兩者之間語法和庫的使用差異哦~

二、git 常用命令

當(dāng)你寫好一段代碼或增刪一些文件后,會用如下命令查看文件狀態(tài):

git status

確認(rèn)文件狀態(tài)后,會用如下命令將的一個或多個文件(夾)添加到暫存區(qū):

git add [pathspec [pathspec ...]]

然后使用如下命令提交信息:

git commit -m "your commit message" 

最后使用如下命令將提交推送到遠(yuǎn)程倉庫:

git push

我們將使用 click和 gitpython庫來實(shí)現(xiàn)這 4 個子命令。

三、關(guān)于 gitpython

gitpython 是一個和 git 倉庫交互的 Python 第三方庫。我們將借用它的能力來實(shí)現(xiàn)真正的 git 邏輯。

安裝:

pip install gitpython

四、思考

在實(shí)現(xiàn)前,我們不妨先思考下會用到 click的哪些功能?整個程序的結(jié)構(gòu)是怎樣的?

click

git的 4 個子命令的實(shí)現(xiàn)其實(shí)對應(yīng)于四個函數(shù),每個函數(shù)使用 click的 command來裝飾。而對于 git add和 git commit,則分別需要表示參數(shù)的 click.argument和表示選項(xiàng)的 click.option來裝飾。

程序結(jié)構(gòu)

程序結(jié)構(gòu)上:

  • 實(shí)例化 Git對象,供全局使用
  • 定義 cli函數(shù)作為命令組,也就是整個命令程序的入口
  • 定義四個命令對應(yīng)的實(shí)現(xiàn)函數(shù) status、add、commit、push

則基本結(jié)構(gòu)如下:

import os import click from git.cmd import Git

git = Git(os.getcwd()) @click.group() def cli(): """
    git 命令行
    """ pass @cli.command() def status(): """
    處理 status 命令
    """ pass @cli.command() @click.argument('pathspec', nargs=-1) def add(pathspec): """
    處理 add 命令
    """ pass @cli.command() @click.option('-m', 'msg') def commit(msg): """
    處理 -m命令
    """ pass @cli.command() def push(): """
    處理 push 命令
    """ pass if __name__ == '__main__':
    cli()

下面我們將一步步地實(shí)現(xiàn)我們的 git程序。

五、實(shí)現(xiàn)

假定我們在 click-git.py 文件中實(shí)現(xiàn)我們的 git程序。

5.1 status 子命令

status子命令不接受任何參數(shù)和選項(xiàng),因此其實(shí)現(xiàn)函數(shù)只需 cli.command()裝飾。

@cli.command() def status(): """
    處理 status 命令
    """ cmd = ['git', 'status']
    output = git.execute(cmd)
    click.echo(output)

不難看出,我們最后調(diào)用了真正的 git status來實(shí)現(xiàn),并打印了輸出。

5.2 add 子命令

add子命令相對于 status子命令,需要接受任意個 pathspec 參數(shù),因此增加一個 click.argument裝飾器,并且在 add函數(shù)中需要增加同名的 pathspec入?yún)?。?jīng) click處理后的 pathspec其實(shí)是個元組,和列表相加前,需要先轉(zhuǎn)換為列表。

@cli.command() @click.argument('pathspec', nargs=-1) def add(pathspec): """
    處理 add 命令
    """ cmd = ['git', 'add'] + list(pathspec)
    output = git.execute(cmd)
    click.echo(output)

當(dāng)我們執(zhí)行 python3 click-git.py add --help時,結(jié)果如下:

Usage: click-git.py add [OPTIONS] [PATHSPEC]...

  處理 add 命令

Options:
  --help  Show this message and exit.

既然 git add能接受任意多個 pathspec,那么 add(pathspec)的參數(shù)其實(shí)改為復(fù)數(shù)形式更為合適,但我們又希望幫助信息中是單數(shù)形式,這就需要額外指定 metavar,則有:

@cli.command() @click.argument('pathspecs', nargs=-1, metavar='[PATHSPEC]...') def add(pathspecs): """
    處理 add 命令
    """ cmd = ['git', 'add'] + list(pathspecs)
    output = git.execute(cmd)
    click.echo(output)

5.3 commit 子命令

add子命令相對于 status子命令,需要接受 -m選項(xiàng),因此增加一個 click.option裝飾器,指定選項(xiàng)名稱 msg,并且在 commit函數(shù)中增加同名入?yún)ⅰ?

@cli.command() @click.option('-m', 'msg') def commit(msg): """
    處理 -m命令
    """ cmd = ['git', 'commit', '-m', msg]
    output = git.execute(cmd)
    click.echo(output)

5.4 push 子命令

push子命令同 status子命令一樣,不接受任何參數(shù)和選項(xiàng),因此其實(shí)現(xiàn)函數(shù)只需 cli.command()裝飾。

@cli.command() def push(): """
    處理 push 命令
    """ cmd = ['git', 'push']
    output = git.execute(cmd)
    click.echo(output)

至此,我們就實(shí)現(xiàn)了一個簡單的 git命令行,使用 python click-git.py status便可查詢項(xiàng)目狀態(tài)。

非常方便的是,每個命令函數(shù)的 docstring都將作為這個命令的幫助信息,因此,當(dāng)我們執(zhí)行 python3 click-git.py --help會自動生成如下幫助內(nèi)容:

Usage: click-git.py [OPTIONS] COMMAND [ARGS]...

  git 命令行

Options:
  --help  Show this message and exit.

Commands:
  add     處理 add 命令
  commit  處理 -m命令
  push    處理 push 命令
  status  處理 status 命令

想看整個源碼,請戳 click-git.py 。

六、小結(jié)

本文簡單介紹了日常工作中常用的 git命令,然后提出實(shí)現(xiàn)它的思路,最終一步步地使用 click和 gitpython實(shí)現(xiàn)了 git程序。

對比 argparse和 click的實(shí)現(xiàn)版本,你會發(fā)現(xiàn)使用 click來實(shí)現(xiàn)變得特定簡單:

  • 相較于 argparse,子解析器、參數(shù)類型什么的統(tǒng)統(tǒng)不需要關(guān)心
  • 相較于 docopt,參數(shù)解析和命令調(diào)用處理也不需要關(guān)心

這無疑是 click最大的優(yōu)勢了。

關(guān)于 click的講解將告一段落,回顧下 click的至簡之道,你會愛上它。

現(xiàn)在,你已學(xué)會了三個命令行解析庫的使用了。但你以為這就夠了嗎?click已經(jīng)夠簡單了吧,夠直接了吧?但它仍然不是最簡單的。

在下篇文章中,將為大家介紹一個由谷歌出品的在 Python 界很火的命令行庫 —— fire。


本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
關(guān)閉