Skip to content

Commit c8c2eec

Browse files
committed
新增“Python 命令行之旅:初探 fire”
1 parent ba459b9 commit c8c2eec

File tree

2 files changed

+130
-0
lines changed

2 files changed

+130
-0
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
- 3.4 [深入 click(三)](contents/Python/cmdline/click-4.md)
3030
- 3.5 [深入 click(四)](contents/Python/cmdline/click-5.md)
3131
- 3.6 [使用 click 实现 git 命令](contents/Python/cmdline/click-6.md)
32+
- 4.1 [初探 fire](contents/Python/cmdline/fire-1.md)
3233
2. [用 Python 生成有“灵魂”的二维码:QRcode](contents/Python/QRcode/content.md)
3334
3. 聊聊 Python 的单元测试框架
3435
- 3.1 [unittest](contents/Python/unittest/unittest.md)

contents/Python/cmdline/fire-1.md

+129
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
# Python 命令行之旅:初探 fire
2+
3+
## 一、前言
4+
5+
在本系列前面所有文章中,我们分别介绍了 `argparse``docopt``click` 的主要功能和用法。它们各具特色,都能出色地完成命令行任务。`argparse` 是面向过程的,需要先设置解析器,再定义参数,再解析命令行,最后实现业务逻辑。`docopt` 先用声明式的语法定义出参数,再过程式地解析命令行和实现业务逻辑。`click` 则是用装饰器的方式进一步简化显式的命令调用逻辑,但仍然不够面向对象。
6+
7+
而今天要介绍的 [fire](https://github.com/google/python-fire) 则是用一种面向广义对象的方式来玩转命令行,这种对象可以是类、函数、字典、列表等,它更加灵活,也更加简单。
8+
9+
```
10+
本系列文章默认使用 Python 3 作为解释器进行讲解。
11+
若你仍在使用 Python 2,请注意两者之间语法和库的使用差异哦~
12+
```
13+
14+
## 二、介绍
15+
16+
[fire](https://github.com/google/python-fire) 可以根据任何 Python 对象自动生成命令行接口。它有如下特性:
17+
18+
- 能以简单的方式生成 CLI
19+
- 是一个开发和调试 Python 代码的实用工具
20+
- 能将现存代码或别人的代码转换为 CLI
21+
- 使得在 Bash 和 Python 间的转换变得更容易
22+
- 通过预先为 REPL 设置所需的模块和变量,使得实用 REPL 更加容易
23+
24+
通过如下命令可快速安装 `fire` 库:
25+
26+
```bash
27+
pip install fire
28+
```
29+
30+
## 三、快速开始
31+
32+
回忆下使用 `argparse``docopt``click` 实现命令行程序的步骤:
33+
34+
- 对于 `argparse` 来说,要先设置解析器,再定义参数,再解析命令行,最后实现业务逻辑
35+
- 对于 `docopt` 来说,要先定义定义接口描述,再解析命令行,最后实现业务逻辑
36+
- 对于 `click` 来说,就是实现业务逻辑和通过装饰器的方式定义参数
37+
38+
它们的实现步骤越来越简单,从四步简化到了两步。而今天的主角 `fire` 则是跟进一步,只需实现业务逻辑就够了。
39+
40+
这简直简单的不可思议,为什么这样做就够了?我们不妨考虑下 Python 中的函数,函数是不是可以对应一个命令行程序,而函数的参数可以对应命令行程序的参数和选项呢?再看看 Python 中的类,一个类是不是可以对应一个命令行程序,而类中的每个实例方法就可以对应子命令,实例方法中的参数就是对应子命令的参数和选项。
41+
42+
这么一想,理论上确实是可以实现的,我们不妨通过下面的示例来看看 `fire` 是如何让我们通过简单的方式实现命令行程序。
43+
44+
### 3.1 使用函数
45+
46+
来看这么一个例子:
47+
48+
```python
49+
import fire
50+
51+
def hello(name="World"):
52+
return 'Hello {name}!'.format(name=name)
53+
54+
if __name__ == '__main__':
55+
fire.Fire(hello)
56+
```
57+
58+
在上述例子中定义一个 `hello` 函数,它接受 `name` 参数,并且有默认值 "World"。使用 `fire.Fire(hello)` 即可非常简单快速地实现命令功能,这个命令行就接受 `--name` 选项,不提供时使用默认值 "World",提供时就按提供的值来。
59+
60+
可在命令行中执行下列命令:
61+
62+
```bash
63+
$ python hello.py
64+
Hello World!
65+
$ python hello.py --name=Prodesire
66+
Hello Prodesire!
67+
$ python hello.py --help
68+
INFO: Showing help with the command 'hello.py -- --help'.
69+
70+
NAME
71+
hello.py
72+
73+
SYNOPSIS
74+
hello.py <flags>
75+
76+
FLAGS
77+
--name=NAME
78+
```
79+
80+
### 3.2 使用类
81+
82+
使用函数是最简单的方式,如果我们想以更有组织的方式来实现,比如使用类,`fire` 也是支持的。
83+
84+
```python
85+
import fire
86+
87+
class Calculator(object):
88+
"""A simple calculator class."""
89+
90+
def double(self, number):
91+
return 2 * number
92+
93+
def triple(self, number):
94+
return 3 * number
95+
96+
if __name__ == '__main__':
97+
fire.Fire(Calculator)
98+
```
99+
100+
在上述例子中定义一个 `Calculator` 类,它有两个实例方法 `double``triple`,并且都接受 `number` 参数,没有默认值。使用 `fire.Fire(Calculator)` 即可非常简单快速地实现命令功能,这个命令行支持两个子命令 `double``triple`,位置参数 `NUMBER` 或选项参数 `--number`
101+
102+
可在命令行中执行下列命令:
103+
104+
```bash
105+
$ python calculator.py double 10
106+
20
107+
$ python calculator.py triple --number=15
108+
45
109+
$ python calculator.py double --help
110+
INFO: Showing help with the command 'calculator.py double -- --help'.
111+
112+
NAME
113+
calculator.py double
114+
115+
SYNOPSIS
116+
calculator.py double NUMBER
117+
118+
POSITIONAL ARGUMENTS
119+
NUMBER
120+
121+
NOTES
122+
You can also use flags syntax for POSITIONAL ARGUMENTS
123+
```
124+
125+
## 四、小结
126+
127+
`fire` 的使用方式非常简单,定一个 Python 对象,剩下的就交给 `fire` 来处理,可谓是非常的 Pythonic,这也是它会如此受欢迎的原因。
128+
129+
除了上面展示的内容,`fire` 还支持更多种类的 Python 对象,也拥有很多强大的功能,我们将在接下来几节中逐步走近它。

0 commit comments

Comments
 (0)