Google 开源的 Python 命令行库:深入 fire(一)
2019-12-31 08:55
1641 查看
[p]
作者:HelloGitHub-Prodesire
HelloGitHub 的《讲解开源项目》系列,项目地址:https://github.com/HelloGitHub-Team/Article
一、前言
在第一篇“初探 fire”的文章中,我们初步掌握了使用
fire的简单步骤,了解了它 Pythonic 的用法。
今天我们将深入了解
fire的子命令、嵌套命令和属性访问功能。
本系列文章默认使用 Python 3 作为解释器进行讲解。 若你仍在使用 Python 2,请注意两者之间语法和库的使用差异哦~
二、功能
2.1 子命令
使用
fire实现子命令有多种方式:
2.1.1 定义若干函数,使用 fire.Fire()
实现子命令最简单的方式就是定义若干个函数,每个函数名隐式就是子命令名称,然后调用
fire.Fire()变将当前模块所有的函数解析为对应的子命令的处理函数。
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是作为数字而非字符串,我们会在下篇文章的参数解析章节中进行讲解。
2.1.2 定义若干函数,使用 fire.Fire()
在
2.1.1的版本中,会把所有函数都当做是子命令。有时我们可能只想把部分函数当做子命令,或者是希望子命令名称和函数名称不一样。这个时候我们就可以通过字典对象显式地告诉
fire。
字典对象的形式为
{'子命令名称': 函数},比如前面的示例中,我们希望最终的子命令为
add和
mul,那么就可以这么写:
fire.Fire({ 'add': add, 'mul': multiply, })
然后我们就可以在命令行中这么调用:
$ python example.py add 10 20 30 $ python example.py mul 10 20 200
2.1.3 定义类和方法,使用 fire.Fire()
定义类和方法的这种方式我们在上一篇文章中介绍过,它和定义函数的方式基本相同,只不过是用类的方式来组织。
然后将类实例化,并把实例化的对象多为
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.4 定义类和方法,使用 fire.Fire()
和
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
2.2 命令组/嵌套命令
想要实现嵌套命令,可将多个类组织起来,示例如下:
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.
2.3 属性访问
属性访问是
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 选项等更加高阶的功能。
『讲解开源项目系列』——让对开源项目感兴趣的人不再畏惧、让开源项目的发起者不再孤单。跟着我们的文章,你会发现编程的乐趣、使用和发现参与开源项目如此简单。欢迎留言联系我们、加入我们,让更多人爱上开源、贡献开源~
相关文章推荐
- Google 开源的 Python 命令行库:初探 fire
- Google的Python开源Fire工具使用笔记
- Python Fire开源—用于自动生成命令行界面的内容库
- 玩转Google开源C++单元测试框架Google Test系列(gtest)之七 - 深入解析gtest
- Google开源的Python格式化工具YAPF的安装和使用教程
- 玩转 Google开源C++单元测试框架Google Test系列(gtest)之七 - 深入解析gtest(转载)
- 玩转Google开源C++单元测试框架Google Test系列(gtest)之七 - 深入解析gtest
- (转)玩转Google开源C++单元测试框架Google Test系列(gtest)之七 - 深入解析gtest
- 深入理解python 命令行解析模块optparse(optparse源代码解读)
- 【转】玩转Google开源C++单元测试框架Google Test系列(gtest)之七 - 深入解析gtest
- 玩转Google开源C++单元测试框架Google Test系列(gtest)之七 - 深入解析gtest
- 谷歌开源 Python Fire:可自动生成命令行接口
- Google开源的Python格式化工具YAPF的安装和使用教程
- 玩转Google开源C++单元测试框架Google Test系列(gtest)之七 - 深入解析gtest
- 玩转Google开源C++单元测试框架Google Test系列(gtest)之七 - 深入解析gtest
- 进阶fPython 命令行 深入 click 之选项
- Google开源了Abseil,为C++和Python开发提供支持
- PYTHON风格规范-Google 开源项目风格指南
- Python 命令行之旅:深入 click 之增强功能
- 使用谷歌(Google)TTS服务 – Java版开源gTTS及Python gTTS