Python 編寫命令行工具竟如此簡單好用

提到編寫命令行工具,你可定會想到 sys.argv 和標準庫 argparse,沒錯,這兩個可以用,只是沒有那麼方便和高效。今天分享兩個工具,讓你編寫命令行工具不費吹灰之力。

1. python-fire

python-fire 是一個三方庫,可以將任何 Python 對象變成一個命令行接口。

使用前先 pip install fire 下。

可以把你的函數直接變成命令行接口:

import fire

def hello(name="World"):
  return "Hello %s!" % name

if __name__ == '__main__':
  fire.Fire(hello)

然後在命令行,就可以執行這些命令:

python hello.py  # Hello World!
python hello.py --name=David  # Hello David!
python hello.py --help  # Shows usage information.

也可以把可以把你的類直接變成命令行接口:

import fire

class Calculator(object):
  """A simple calculator class."""

  def double(self, number):
    return 2 * number

if __name__ == '__main__':
  fire.Fire(Calculator)

然後就可以這樣執行:

python calculator.py double 10  # 20
python calculator.py double --number=15  # 30

除此之外,還有這樣的功能:

執行後自動進入交互模式:

command -- --interactive

比如:

查看執行的調用順序:

python arg_demo2.py double 10 -- --trace

結果如下:

還可以爲你生成 shell 自動補全命令的腳本,真的很貼心:

python arg_demo2.py double 10 -- --completion

2. mando

mando 是一個基於 argparse 的裝飾器,可以讓你在幾秒內編寫出一個靈活、可維護的命令行工具。

使用前先 pip install mando 下。

用法:

example.py

from mando import command, main

@command
def echo(text, capitalize=False):
    '''Echo the given text.'''
    if capitalize:
        text = text.upper()
    print(text)

if __name__ == '__main__':
    main()

命令行用法:

$ python example.py -h
usage: example.py [-h] {echo} ...

positional arguments:
  {echo}
    echo      Echo the given text.

optional arguments:
  -h, --help  show this help message and exit

$ python example.py echo -h
usage: example.py echo [-h] [--capitalize] text

Echo the given text.

positional arguments:
  text

optional arguments:
  -h, --help    show this help message and exit
  --capitalize

真實執行結果:

$ python example.py echo spam
spam
$ python example.py echo --capitalize spam
SPAM

再複雜一點的:

from mando import command, main


@command
def push(repository, all=False, dry_run=False, force=False, thin=False):
    '''Update remote refs along with associated objects.

    :param repository: Repository to push to.
    :param --all: Push all refs.
    :param -n, --dry-run: Dry run.
    :param -f, --force: Force updates.
    :param --thin: Use thin pack.'''

    print ('Pushing to {0}. All: {1}, dry run: {2}, force: {3}, thin: {4}'
           .format(repository, all, dry_run, force, thin))


if __name__ == '__main__':
    main()


mando 可以理解 Sphinx 風格的文檔字符串中的 :param 參數說明,因此可以顯示幫助文檔。

$ python git.py push -h
usage: git.py push [-h] [--all] [-n] [-f] [--thin] repository

Update remote refs along with associated objects.

positional arguments:
  repository     Repository to push to.

optional arguments:
  -h, --help     show this help message and exit
  --all          Push all refs.
  -n, --dry-run  Dry run.
  -f, --force    Force updates.
  --thin         Use thin pack.

mando 還可以理解 Python3 的類型提示,因此傳錯了參數,也會有報錯提示:

from mando import command, main


@command
def duplicate(string, times: int):
    '''Duplicate text.

    :param string: The text to duplicate.
    :param times: How many times to duplicate.'''

    print(string * times)


if __name__ == '__main__':
    main()

執行:

$ python3 test.py duplicate "test " 5
test test test test test
$ python3 test.py duplicate "test " foo
usage: test.py duplicate [-h] string times
test.py duplicate: error: argument times: invalid int value: 'foo'

最後的話

本文分享編寫建命令行工具的三方庫,使用起來非常簡單,我也是偶然在 GitHub 搜索到的,寫代碼前先在 GitHub 上搜一下是一個很好的習慣,如果覺得有收穫,歡迎關注「Python七號」,每週學習一個小技術。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章