涉及的示例代碼和歷史文章,已同步更新到 HelloGitHub-Team 倉庫python
在第一篇「初探 fire」的文章中,咱們初步掌握了使用 fire
的簡單步驟,瞭解了它 Pythonic 的用法。git
今天咱們將深刻了解 fire
的子命令、嵌套命令和屬性訪問功能。github
本系列文章默認使用 Python 3 做爲解釋器進行講解。
若你仍在使用 Python 2,請注意二者之間語法和庫的使用差別哦~
複製代碼
使用 fire
實現子命令有多種方式:編程
實現子命令最簡單的方式就是定義若干個函數,每一個函數名隱式就是子命令名稱,而後調用 fire.Fire()
變將當前模塊全部的函數解析爲對應的子命令的處理函數。bash
import fire
def add(x, y):
return x + y
def multiply(x, y):
return x * y
if __name__ == '__main__':
fire.Fire()
複製代碼
而後咱們就能夠在命令行中這麼調用:函數
$ python example.py add 10 20
30
$ python example.py multiply 10 20
200
複製代碼
關於如何識別參數類型,好比上述 add 10 20
中 10
和 20
是做爲數字而非字符串,咱們會在下篇文章的參數解析章節中進行講解。ui
在 2.1.1
的版本中,會把全部函數都當作是子命令。有時咱們可能只想把部分函數當作子命令,或者是但願子命令名稱和函數名稱不同。這個時候咱們就能夠經過字典對象顯式地告訴 fire
。編碼
字典對象的形式爲 {'子命令名稱': 函數}
,好比前面的示例中,咱們但願最終的子命令爲 add
和 mul
,那麼就能夠這麼寫:spa
fire.Fire({
'add': add,
'mul': multiply,
})
複製代碼
而後咱們就能夠在命令行中這麼調用:命令行
$ python example.py add 10 20
30
$ python example.py mul 10 20
200
複製代碼
定義類和方法的這種方式咱們在上一篇文章中介紹過,它和定義函數的方式基本相同,只不過是用類的方式來組織。
而後將類實例化,並把實例化的對象多爲 fire.Fire
的入參:
import fire
class Calculator(object):
def add(self, x, y):
return x + y
def multiply(self, x, y):
return x * y
if __name__ == '__main__':
calculator = Calculator()
fire.Fire(calculator)
複製代碼
和 2.1.3
中的惟一不一樣點是把類而非實例對象做爲 fire.Fire
的入參:
fire.Fire(Calculator)
複製代碼
傳遞類和實例對象的基本做用是同樣的,但傳遞類還有一個額外的特性:若是構造函數中定義了參數,那麼這些參數都會做爲整個命令行程序的選項參數。
import fire
class BrokenCalculator(object):
def __init__(self, offset=1):
self._offset = offset
def add(self, x, y):
return x + y + self._offset
def multiply(self, x, y):
return x * y + self._offset
if __name__ == '__main__':
fire.Fire(BrokenCalculator)
複製代碼
查看幫助命令有:
$ python example.py --help
INFO: Showing help with the command 'example.py -- --help'.
NAME
example.py
SYNOPSIS
example.py <flags>
FLAGS
--offset=OFFSET
複製代碼
因而可知構造函數 BrokenCalculator.__init__(self, offset=1)
中的 offset
自動轉換爲了命令行中的全局選項參數 --offset
,且默認值爲 1
。
咱們能夠在命令行中這麼調用:
$ python example.py add 10 20
31
$ python example.py multiply 10 20
201
$ python example.py add 10 20 --offset=0
30
$ python example.py multiply 10 20 --offset=0
200
複製代碼
想要實現嵌套命令,可將多個類組織起來,示例以下:
class IngestionStage(object):
def run(self):
return 'Ingesting! Nom nom nom...'
class DigestionStage(object):
def run(self, volume=1):
return ' '.join(['Burp!'] * volume)
def status(self):
return 'Satiated.'
class Pipeline(object):
def __init__(self):
self.ingestion = IngestionStage()
self.digestion = DigestionStage()
def run(self):
self.ingestion.run()
self.digestion.run()
if __name__ == '__main__':
fire.Fire(Pipeline)
複製代碼
在上面的示例中:
IngestionStage
實現了子命令 run
DigestionStage
實現了子命令 run
和 status
Pipeline
的構造函數中將 IngestionStage
實例化爲 ingestion
,將 DigestionStage
實例化爲 digestion
,就將這兩個放到一個命令組中,於是支持了:
ingestion run
digestion run
digestion status
Pipeline
實現了子命令 run
所以整個命令行程序支持以下命令:
run
ingestion run
digestion run
digestion status
而後咱們就能夠在命令行中這麼調用:
$ python example.py run
Ingesting! Nom nom nom...
Burp!
$ python example.py ingestion run
Ingesting! Nom nom nom...
$ python example.py digestion run
Burp!
$ python example.py digestion status
Satiated.
複製代碼
屬性訪問
是 fire
相對於其餘命令行庫來講一個比較獨特的功能。所謂訪問屬性是獲取預置的屬性所對應的值。
舉個例子,在命令行中指定 --code
來告知程序要查詢的程序編碼,而後但願經過 zipcode
屬性返回郵編,經過 city
屬性返回城市名。那麼屬性可實現爲實例成員屬性:
import fire
cities = {
'hz': (310000, '杭州'),
'bj': (100000, '北京'),
}
class City(object):
def __init__(self, code):
info = cities.get(code)
self.zipcode = info[0] if info else None
self.city = info[1] if info else None
if __name__ == '__main__':
fire.Fire(City)
複製代碼
使用方式以下:
$ python example.py --code bj zipcode
100000
$ python example.py --code hz city
杭州
複製代碼
使用 fire
實現子命令和嵌套命令相對於其餘命令行庫來講都更加簡單清晰,不只如此,fire
還提供了屬性訪問這種較爲獨特的能力。
在下篇文章中,咱們將進一步深刻了解 fire
,介紹其鏈式函數調用、自定義序列化、參數解析、fire 選項等更加高階的功能。
『講解開源項目系列』——讓對開源項目感興趣的人再也不畏懼、讓開源項目的發起者再也不孤單。跟着咱們的文章,你會發現編程的樂趣、使用和發現參與開源項目如此簡單。歡迎留言聯繫咱們、加入咱們,讓更多人愛上開源、貢獻開源~