【Python】自动生成命令行工具 - fire 简介

news/2024/7/23 18:39:02 标签: python

Python 中用于生成命令行接口(Command Line Interfaces, CLIs)的工具已经有一些了,例如已经成为 Python 标准库的 argparse 和第三方的 click ,这些都是很不错的工具。但是这些工具为 Python 程序生成 CLIs 的时候稍显麻烦,需要增加的地方比较多,过程稍显繁琐。今天介绍的这个工具,几乎可以不改变原始代码就可以生成 CLIs,是 Google 于 今年(2017 年)3 月 2 日宣布在 GitHub 上开源的。

fire 开源

文中的三个程序文件可以在 这里 打包下载。


更新

这里我会列出对本文的更新。

  • 2017 年 10 月 18 日:优化排版,与其他博文保持风格统一。

简介

大致的简介我在上面简单说了下,下面我引用下官方简介:

Python Fire is a library for creating command line interfaces (CLIs) from absolutely any Python object.

  • Python Fire is a simple way to create a CLI in Python.
  • Python Fire is a helpful tool for developing and debugging Python code.
  • Python Fire helps with exploring existing code or turning other people’s code into a CLI.
  • Python Fire makes transitioning between Bash and Python easier.
  • Python Fire makes using a Python REPL easier by setting up the REPL with the modules and variables you’ll need already imported and created.

可以看出来,Fire 不仅仅是一个生成 CLIs 的工具,而且还可以调试 Python 程序,交互式的使用 Fire 。


安装

在命令行中运行 pip install fire 即可安装。


用法

使用 fire 生成 CLIs 的基本用法就是使用 fire.Fire(),可以传入任意参数,用官方的说法就是 any Python object 。下面我举三个例子简单的说明一下用法,更多的用法大家可以参考 The Python Fire Guide 和 Using a Fire CLI 。

下面的例子均是以计算时间差(两个日期之间相差的天数)的程序为例。

单个函数

文件 test-fire.py

python hljs  has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace; font-size: 12.6px; white-space: pre; border-radius: 0px; overflow-x: auto; word-wrap: normal;">import fire
import datetime

def cal_days(date_str1, date_str2):
    '''计算两个日期之间的天数'''

    date_str1 = str(date_str1)
    date_str2 = str(date_str2)
    d1 = datetime.datetime.strptime(date_str1, '%Y%m%d')
    d2 = datetime.datetime.strptime(date_str2, '%Y%m%d')
    delta = d1 - d2
    return delta.days


if __name__ == '__main__':
    fire.Fire(cal_days)
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

这个程序中只有一个函数 cal_days,最后使用 fire.Fire(cal_days) 来生成 CLIs。

我们可以先用下面的语句查看帮助信息:

$ python test-fire.py
Fire trace:
1. Initial component
2. ('The function received no value for the required argument:', 'date_str1')

Type:        function
String form: <function cal_days at 0x000002F0099B7F28>
File:        d:\masterfiles\notebook\test-fire.py
Line:        4
Docstring:   计算两个日期之间的天数

Usage:       test-fire.py DATE_STR1 DATE_STR2
             test-fire.py --date-str1 DATE_STR1 --date-str2 DATE_STR2
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

我们可以看到传给 fire.Fire() 的参数类型(function)、文件路径、文档字符串、参数用法等信息。

现在我们试着计算一下 2017 年 4 月 21 号和 2017 年 4 月 1 号差了多少天:

$ python test-fire.py 20170421 20170401
20
 
  • 1
  • 2

当然,你也可以使用 python test-fire.py --date-str1 20170421 --date-str2 20170401

此外,对于这种单个函数的情况,程序的最后一行 fire.Fire(cal_days) 可以改为 fire.Fire(),结果完全一样,fire.Fire() 会默认使用 cal_days() 函数。


多个函数

文件 test-fire-2func.py

python hljs  has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace; font-size: 12.6px; white-space: pre; border-radius: 0px; overflow-x: auto; word-wrap: normal;">import fire
import datetime

def cal_days(date_str1, date_str2):
    '''计算两个日期之间的天数'''

    date_str1 = str(date_str1)
    date_str2 = str(date_str2)
    d1 = datetime.datetime.strptime(date_str1, '%Y%m%d')
    d2 = datetime.datetime.strptime(date_str2, '%Y%m%d')
    delta = d1 - d2
    return delta.days


def days2today(date_str):
    '''计算某天距离今天的天数'''

    date_str = str(date_str)
    d = datetime.datetime.strptime(date_str, '%Y%m%d')
    delta = datetime.datetime.now() - d
    return delta.days


if __name__ == '__main__':
    fire.Fire()
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

这个程序比 test-fire.py 多了一个函数,但是结尾处仍然使用 fire.Fire() 来生成 CLIs。我们先不输任何参数:

$ python test-fire-2func.py 20170401
Fire trace:
1. Initial component
2. ('Cannot find target in dict', '20170401', {'__name__': '__main__', 'datetime': <module 'datetime' from 'C:\\Users\\secsi\\Anaconda3\\lib\\datetime.py'>, 'cal_days': <function cal_days at 0x0000027A855E7F28>, 'days2today': <function days2today at 0x0000027A86EC6B70>, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000027A85655A90>, '__file__': 'test-fire-2func.py', '__cached__': None, 'fire': <module 'fire' from 'C:\\Users\\secsi\\Anaconda3\\lib\\site-packages\\fire\\__init__.py'>, '__package__': None, '__builtins__': <module 'builtins' (built-in)>, '__doc__': None, '__spec__': None})

Type:        dict
String form: {'__name__': '__main__', 'datetime': <module 'datetime' from 'C:\\Users\\secsi\\Anaconda3\\lib\\d <...> kage__': None, '__builtins__': <module 'builtins' (built-in)>, '__doc__': None, '__spec__': None}
Length:      12

Usage:       test-fire-2func.py
             test-fire-2func.py datetime
             test-fire-2func.py cal-days
             test-fire-2func.py days2today
             test-fire-2func.py fire
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

程序中有个两个函数,而我们运行 python test-fire-2func.py 20170401 的时候却没有指定使用哪个函数,所以会报错。

正确的写法应该是这样的:

$ python test-fire-2func.py days2today 20170401
21
$ python test-fire-2func.py cal_days 20170422 20170401
21
 
  • 1
  • 2
  • 3
  • 4

也就是说在后面跟上要使用的函数名。


对象(类)

Fire 既然能够 fire 任何 Python 对象,那么给 fire.Fire() 传一个类也是完全可以的。下面是一个例子:

文件 test-fire-class.py

python hljs  has-numbering" style="display: block; padding: 0px; background: transparent; color: inherit; box-sizing: border-box; font-family: "Source Code Pro", monospace; font-size: 12.6px; white-space: pre; border-radius: 0px; overflow-x: auto; word-wrap: normal;">import fire
import datetime


class DateStr(object):

    def cal_days(self, date_str1, date_str2):
        '''计算两个日期之间的天数'''
        date_str1 = str(date_str1)
        date_str2 = str(date_str2)
        d1 = datetime.datetime.strptime(date_str1, '%Y%m%d')
        d2 = datetime.datetime.strptime(date_str2, '%Y%m%d')
        delta = d1 - d2
        return delta.days

    def days2today(self, date_str):
        '''计算某天距离今天的天数'''
        date_str = str(date_str)
        d = datetime.datetime.strptime(date_str, '%Y%m%d')
        delta = datetime.datetime.now() - d
        return delta.days


if __name__ == '__main__':
    fire.Fire(DateStr)
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

这里我定义了一个 DateStr 类,有两个类方法 cal_days 和 days2today ,那么我只需 fire.Fire(DateStr) 就可以调用这两个类方法。

$  python test-fire-class.py days2today 20170401
21
$ python test-fire-class.py cal-days 20170422 20170401
21
 
  • 1
  • 2
  • 3
  • 4

还有几点

  • fire 默认使用 - 作为参数分隔符,所以如果你要在命令行传入类似 2017-04-22 的参数时,那么程序接收到的参数就肯定不是 2017-04-22 了,你需要使用 --separator 来改变分隔符,参考 Changing the Separator
  • fire 会自动区分你在命令行传入的参数的类型,例如 20170422 会自动识别成 inthello 会自动识别成 str'(1,2)' 会自动识别成 tuple'{"name": "Alan Lee"}' 会自动识别成 dict。但是你如果想要传入一个字符串类型的 20170422 怎么办?那就需要这样写:'"20170422"' 或者 "'20170422'" 或者 \"20170422\",总之呢,就是加一个转义,因为命令行默认会吃掉你的引号。参考 Argument Parsing

END


http://www.niftyadmin.cn/n/1145275.html

相关文章

准确率(Accuracy), 精确率(Precision), 召回率(Recall)和F1-Measure

机器学习(ML),自然语言处理(NLP),信息检索(IR)等领域,评估(Evaluation)是一个必要的 工作,而其评价指标往往有如下几点:准确率(Accuracy),精确率(Precision),召回率(Recall)和F1-Measure。(注&#xff1a; 相对来说&#xff0c;IR 的 ground truth 很多时候是一个 Ordered List…

【LaTeX】TeXworks的自动补全功能分类解析

不得不说&#xff0c;用了这么久的 TW &#xff0c;我对它的了解也不是很清楚&#xff0c;可能是因为我太懒了吧&#xff0c;没有去挖掘发现TW的强大之处。对于TW的自动补全&#xff0c;我原先一直指责做得不好&#xff0c;最近才发现&#xff0c;真的很强大&#xff0c;如果用…

python PIL 图像处理模块以及array的互相转换,基本图像处理收集

http://pillow.readthedocs.org/en/3.1.x/reference/Image.htmlhttp://blog.csdn.net/xueweuchen/article/details/38756075http://python-reference.readthedocs.org/en/latest/docs/functions/bytearray.htmlhttps://github.com/yipinp/ADAS_LabPIL 库中比较好用的就是fromar…

web.py 学习之 helloworld

前言 晚上1点躺在床上&#xff0c;但是一直没睡着&#xff0c;我想了一下&#xff0c;目前的学习好像python这块&#xff0c;除了基本的语法学习过了&#xff0c;但是关于web.py的使用还是一直没学会&#xff0c;所以又爬起来打开电脑&#xff0c;再看看这个东西。结果he…

简单而直接的Python web 框架:web.py

From&#xff1a;https://www.oschina.net/question/5189_4306 Web.py github 地址&#xff1a;https://github.com/webpy/webpy https://pypi.python.org/pypi/web.py Web.py Cookbook 简体中文版&#xff1a;http://webpy.org/cookbook/index.zh-cn web.py 0.3 新手…

windows下安装web.py快速指南(py3版本安装出错的原因)

环境介绍 首先介绍下安装使用的环境 - Windows 7 - Python 3.6 Web.py介绍 web.py是Python在Web领域一个轻量级的解决方案&#xff0c;所谓轻量&#xff0c;就是非常简单快速满足Web页面开发的需求。 首先来感受一下其轻量的程度吧&#xff1a; import weburls (/(.*), he…

python字符串前面加u,r,b的含义

u/U:表示unicode字符串 不是仅仅是针对中文, 可以针对任何的字符串&#xff0c;代表是对字符串进行unicode编码。 一般英文字符在使用各种编码下, 基本都可以正常解析, 所以一般不带u&#xff1b;但是中文, 必须表明所需编码, 否则一旦编码转换就会出现乱码。 建议所有编码方…

关于Zookeeper的若干个重要问题

Zookeeper 1.Zookeeper有哪些节点类型&#xff1f; PERSISTENT-持久节点 除非手动删除&#xff0c;否则节点一直存在于Zookeeper上 EPHEMERAL-临时节点 临时节点的生命周期与客户端会话绑定&#xff0c;一旦客户端会话失效&#xff08;客户端与zookeeper连接断开不一定会话失…