1. 程式人生 > >帶你瞭解3個Python命令列工具

帶你瞭解3個Python命令列工具

用 Click、Docopt 和 Fire 庫寫你自己的命令列應用。

有時對於某項工作來說一個命令列工具就足以勝任。命令列工具是一種從你的 shell 或者終端之類的地方互動或執行的程式。Git 和 Curl 就是兩個你也許已經很熟悉的命令列工具。

當你有一小段程式碼需要在一行中執行多次或者經常性地被執行,命令列工具就會很有用。Django 開發者執行 ./manage.py runserver 命令來啟動他們的網路伺服器;Docker 開發者執行 docker-compose up 來啟動他們的容器。你想要寫一個命令列工具的原因可能和你一開始想寫程式碼的原因有很大不同。

對於這個月的 Python 專欄,我們有 3 個庫想介紹給希望為自己編寫命令列工具的 Python 使用者。

Click

Click 是我們最愛的用來開發命令列工具的 Python 包。其:

  • 有一個富含例子的出色文件
  • 包含說明如何將命令列工具打包成一個更加易於執行的 Python 應用程式
  • 自動生成實用的幫助文字
  • 使你能夠疊加使用可選和必要引數,甚至是 多個命令
  • 有一個 Django 版本( django-click )用來編寫管理命令

Click 使用 @click.command() 去宣告一個函式作為命令,同時可以指定必要和可選引數。

  1. # hello.py
  2. import click
  3. @click.command()
  4. @click.option('--name',default='', help='Your name'
    )
  5. def say_hello(name):
  6. click.echo("Hello {}!".format(name))
  7. if __name__ =='__main__':
  8. say_hello()

@click.option() 修飾器聲明瞭一個 可選引數 ,而 @click.argument() 修飾器聲明瞭一個必要引數。你可以通過疊加修飾器來組合可選和必要引數。echo() 方法將結果列印到控制檯。

  1. $ python hello.py --name='Lacey'
  2. HelloLacey!

Docopt

Docopt 是一個命令列工具的解析器,類似於命令列工具的 Markdown。如果你喜歡流暢地編寫應用文件,在本文推薦的庫中 Docopt 有著最好的格式化幫助文字。它不是我們最愛的命令列工具開發包的原因是它的文件猶如把人扔進深淵,使你開始使用時會有一些小困難。然而,它仍是一個輕量級的、廣受歡迎的庫,特別是當一個漂亮的說明文件對你來說很重要的時候。

Docopt 對於如何格式化文章開頭的 docstring 是很特別的。在工具名稱後面的 docsring 中,頂部元素必須是 Usage: 並且需要列出你希望命令被呼叫的方式(比如:自身呼叫,使用引數等等)。Usage: 需要包含 help 和 version 引數。

docstring 中的第二個元素是 Options:,對於在 Usages: 中提及的可選項和引數,它應當提供更多的資訊。你的 docstring 的內容變成了你幫助文字的內容。

  1. """HELLO CLI
  2. Usage:
  3. hello.py
  4. hello.py <name>
  5. hello.py -h|--help
  6. hello.py -v|--version
  7. Options:
  8. <name> Optional name argument.
  9. -h --help Show this screen.
  10. -v --version Show version.
  11. """
  12. from docopt import docopt
  13. def say_hello(name):
  14. return("Hello {}!".format(name))
  15. if __name__ =='__main__':
  16. arguments = docopt(__doc__, version='DEMO 1.0')
  17. if arguments['<name>']:
  18. print(say_hello(arguments['<name>']))
  19. else:
  20. print(arguments)

在最基本的層面,Docopt 被設計用來返回你的引數鍵值對。如果我不指定上述的 name 呼叫上面的命令,我會得到一個字典的返回值:

  1. $ python hello.py
  2. {'--help':False,
  3. '--version':False,
  4. '<name>':None}

這裡可看到我沒有輸入 help 和 version 標記並且 name 引數是 None

但是如果我帶著一個 name 引數呼叫,say_hello 函式就會執行了。

  1. $ python hello.py Jeff
  2. HelloJeff!

Docopt 允許同時指定必要和可選引數,且各自有著不同的語法約定。必要引數需要在ALLCAPS 和 <carets> 中展示,而可選引數需要單雙橫槓顯示,就像 --like。更多內容可以閱讀 Docopt 有關 patterns 的文件。

Fire

Fire 是谷歌的一個命令列工具開發庫。尤其令人喜歡的是當你的命令需要更多複雜引數或者處理 Python 物件時,它會聰明地嘗試解析你的引數型別。

Fire 的 文件 包括了海量的樣例,但是我希望這些文件能被更好地組織。Fire 能夠處理 同一個檔案中的多條命令、使用 物件 的方法作為命令和 分組 命令。

它的弱點在於輸出到控制檯的文件。命令列中的 docstring 不會出現在幫助文字中,並且幫助文字也不一定標識出引數。

  1. import fire
  2. def say_hello(name=''):
  3. return'Hello {}!'.format(name)
  4. if __name__ =='__main__':
  5. fire.Fire()

引數是必要還是可選取決於你是否在函式或者方法定義中為其指定了一個預設值。要呼叫命令,你必須指定檔名和函式名,比較類似 Click 的語法:

  1. $ python hello.py say_hello Rikki
  2. HelloRikki!

你還可以像標記一樣傳參,比如 --name=Rikki

額外贈送:打包!

Click 包含了使用 setuptools 打包 命令列工具的使用說明(強烈推薦按照說明操作)。

要打包我們第一個例子中的命令列工具,將以下內容加到你的 setup.py 檔案裡:

  1. from setuptools import setup
  2. setup(
  3. name='hello',
  4. version='0.1',
  5. py_modules=['hello'],
  6. install_requires=[
  7. 'Click',
  8. ],
  9. entry_points='''
  10. [console_scripts]
  11. hello=hello:say_hello
  12. ''',
  13. )

任何你看見 hello 的地方,使用你自己的模組名稱替換掉,但是要記得忽略 .py 字尾名。將say_hello 替換成你的函式名稱。

然後,執行 pip install --editable 來使你的命令在命令列中可用。

現在你可以呼叫你的命令,就像這樣:

  1. $ hello --name='Jeff'
  2. HelloJeff!

通過打包你的命令,你可以省掉在控制檯鍵入 python hello.py --name='Jeff' 這種額外的步驟以減少鍵盤敲擊。這些指令也很可能可在我們提到的其他庫中使用。

python學習交流群:125240963

轉載至:https://linux.cn/article-9807-1.html