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


一、前言

在第一篇“初探 fire”的文章中,我們初步掌握了使用 fire的簡單步驟,了解了它 Pythonic 的用法。

今天我們將深入了解 fire的子命令、嵌套命令和屬性訪問功能。

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

二、功能

2.1 子命令

使用 fire實現(xiàn)子命令有多種方式:

2.1.1 定義若干函數(shù),使用 fire.Fire()

實現(xiàn)子命令最簡單的方式就是定義若干個函數(shù),每個函數(shù)名隱式就是子命令名稱,然后調(diào)用 fire.Fire()變將當(dāng)前模塊所有的函數(shù)解析為對應(yīng)的子命令的處理函數(shù)。

import fire def add(x, y): return x + y def multiply(x, y): return x * y if __name__ == '__main__':
  fire.Fire()

然后我們就可以在命令行中這么調(diào)用:

$ python example.py add 10 20
30
$ python example.py multiply 10 20
200

關(guān)于如何識別參數(shù)類型,比如上述 add 10 20中 10和 20是作為數(shù)字而非字符串,我們會在下篇文章的參數(shù)解析章節(jié)中進行講解。

2.1.2 定義若干函數(shù),使用 fire.Fire()

2.1.1的版本中,會把所有函數(shù)都當(dāng)做是子命令。有時我們可能只想把部分函數(shù)當(dāng)做子命令,或者是希望子命令名稱和函數(shù)名稱不一樣。這個時候我們就可以通過字典對象顯式地告訴 fire。

字典對象的形式為 {'子命令名稱': 函數(shù)},比如前面的示例中,我們希望最終的子命令為 add和 mul,那么就可以這么寫:

fire.Fire({ 'add': add, 'mul': multiply,
})

然后我們就可以在命令行中這么調(diào)用:

$ python example.py add 10 20
30
$ python example.py mul 10 20
200

sa

2.1.3 定義類和方法,使用 fire.Fire()

定義類和方法的這種方式我們在上一篇文章中介紹過,它和定義函數(shù)的方式基本相同,只不過是用類的方式來組織。

然后將類實例化,并把實例化的對象多為 fire.Fire的入?yún)ⅲ?

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.4 定義類和方法,使用 fire.Fire()

2.1.3中的唯一不同點是把類而非實例對象作為 fire.Fire的入?yún)ⅲ?

fire.Fire(Calculator)

傳遞類和實例對象的基本作用是一樣的,但傳遞類還有一個額外的特性:如果構(gòu)造函數(shù)中定義了參數(shù),那么這些參數(shù)都會作為整個命令行程序的選項參數(shù)。

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.pyFLAGS
    --offset=OFFSET

由此可見構(gòu)造函數(shù) BrokenCalculator.__init__(self, offset=1)中的 offset自動轉(zhuǎn)換為了命令行中的全局選項參數(shù) --offset,且默認值為 1。

我們可以在命令行中這么調(diào)用:

$ 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

2.2 命令組/嵌套命令

想要實現(xiàn)嵌套命令,可將多個類組織起來,示例如下:

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實現(xiàn)了子命令 run
  • DigestionStage實現(xiàn)了子命令 run和 status
  • Pipeline的構(gòu)造函數(shù)中將 IngestionStage實例化為 ingestion,將 DigestionStage實例化為 digestion,就將這兩個放到一個命令組中,因而支持了:
    • ingestion run
    • digestion run
    • digestion status
  • Pipeline實現(xiàn)了子命令 run

因此整個命令行程序支持如下命令:

  • run
  • ingestion run
  • digestion run
  • digestion status

然后我們就可以在命令行中這么調(diào)用:

$ 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.

2.3 屬性訪問

屬性訪問是 fire相對于其他命令行庫來說一個比較獨特的功能。所謂訪問屬性是獲取預(yù)置的屬性所對應(yīng)的值。

舉個例子,在命令行中指定 --code來告知程序要查詢的程序編碼,然后希望通過 zipcode屬性返回郵編,通過 city屬性返回城市名。那么屬性可實現(xiàn)為實例成員屬性:

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
杭州

三、小結(jié)

使用 fire實現(xiàn)子命令和嵌套命令相對于其他命令行庫來說都更加簡單清晰,不僅如此,fire還提供了屬性訪問這種較為獨特的能力。

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