巧用Google Fire简化Python命令行程序

Google 的用于生成命令行接口的工具 fire 的简单用法 fire 是 Google 开源的用于给任何 Python 程序自动生成命令行接口(CLI)的库,压缩包中包含简单使用例子和详细的使用说明(博客)。 立即下载

Hello World

要介绍Fire是什么,看一个简单的例子就明白了

# calc.py
import fire

class Calculator(object):
  """A simple calculator class."""

  def double(self, number):
    return 2 * number

if __name__ == '__main__':
  fire.Fire(Calculator)

接下来我们进入bash来执行上面编写的脚本

> python calc.py double 10
20
> python calc.py double --number=16
32

上面是官方的示例代码,有了fire,编写Python的命令行程序就变得非常简单,我们无需再去处理繁琐的命令行参数解析了。接下来我们仿照HelloWorld,编写一个圆周率和阶乘计算的命令行脚本。

实战

import math
import fire


class Math(object):

    def pi(self, n):
        s = 0.0
        for i in range(n):
            s += 1.0/(i+1)/(i+1)
        return math.sqrt(6*s)

    def fact(self, n):
        s = 1
        for i in range(n):
            s *= (i+1)
        return s


if __name__ == '__main__':
    fire.Fire(Math)

接下来我们运行一下

>  python maths.py pi 10000
3.14149716395
>  python maths.py pi 100000
3.14158310433
>  python maths.py pi 1000000
3.14159169866
>  python maths.py fact 10
3628800
>  python maths.py fact 15
1307674368000
>  python maths.py fact 20
2432902008176640000

Cool,真的非常方便!fire对当前对象结构进行了暴露,将结构信息映射到shell命令行参数上。fire其实有多种暴露模式,接下来我们逐个来看fire都有哪些暴露模式。

暴露模块

fire如果不传递任何参数就可以直接暴露当前模块结构,我们对上面的例子做一下改造,去掉类信息

import math
import fire


def pi(n):
    s = 0.0
    for i in range(n):
        s += 1.0/(i+1)/(i+1)
    return math.sqrt(6*s)

def fact(n):
    s = 1
    for i in range(n):
        s *= (i+1)
    return s


if __name__ == '__main__':
    fire.Fire()

注意Fire函数调用没有任何参数,运行一下

>  python maths.py fact 20
2432902008176640000
>  python maths.py pi 1000000
3.14159169866

暴露函数

fire还可以传递一个函数对象来暴露单个函数,可以让我们在命令行参数上省掉函数名称

import math
import fire

def pi(n):
    s = 0.0
    for i in range(n):
        s += 1.0/(i+1)/(i+1)
    return math.sqrt(6*s)
    
if __name__ == '__main__':
    fire.Fire(pi)

如果暴露函数那就只能暴露一个函数,如果暴露了两个,那就只有后面一个生效,运行一下

>  python maths.py 1000
3.14063805621

暴露字典

fire可以直接暴露一个模块,将当前模块的所有函数全部暴露,函数名和第一个参数名一致。我们也可以不用暴露整个模块的所有函数,使用字典暴露法就可以选择性地对模块的某些函数进行暴露,顺便还可以替换暴露出来的函数名称。

import math
import fire


def pi(n):
    s = 0.0
    for i in range(n):
        s += 1.0/(i+1)/(i+1)
    return math.sqrt(6*s)

def fact(n):
    s = 1
    for i in range(n):
        s *= (i+1)
    return s


if __name__ == '__main__':
    fire.Fire({
        "pi[n]": pi
    })

我们只暴露了pi函数,并且把名字还换掉了,运行一下,看效果

>  python maths.py pi[n] 1000
3.14063805621

如果我们使用原函数名称,就会看到fire列出的友好的报错信息

>  python maths.py pi 1000
Fire trace:
1. Initial component
2. ('Cannot find target in dict:', 'pi', {'pi[n]': <function pi at 0x10a062c08>})
Type:        dict
String form: {'pi[n]': <function pi at 0x10a062c08>}
Length:      1
Usage:       maths.py
             maths.py pi[n]

暴露对象

import math
import fire


class Maths(object):

    def pi(self, n):
        s = 0.0
        for i in range(n):
            s += 1.0/(i+1)/(i+1)
        return math.sqrt(6*s)

    def fact(self, n):
        s = 1
        for i in range(n):
            s *= (i+1)
        return s


if __name__ == '__main__':
    fire.Fire(Maths())

运行

>  python maths.py pi 1000
3.14063805621
>  python maths.py fact 20
2432902008176640000

暴露类

这个我们在上面的实战环节已经演示过了,这里就不在重复粘贴

类 vs 对象

通过上面的例子,我们发现暴露类和暴露对象似乎没有任何区别,那到底该选哪种比较优雅呢?这个要看类的构造器有没有参数,如果是不带参数的构造器,那么类和对象的暴露是没有区别的,但是如果类的构造器有参数,那就不一样了,下面我们改造一下Maths类,增加一个放大系数。

import math
import fire


class Maths(object):

    def __init__(self, coeff):
        self.coeff = coeff

    def pi(self, n):
        s = 0.0
        for i in range(n):
            s += 1.0/(i+1)/(i+1)
        return self.coeff * math.sqrt(6*s)

    def fact(self, n):
        s = 1
        for i in range(n):
            s *= (i+1)
        return self.coeff * s


if __name__ == '__main__':
    fire.Fire(Maths)

因为Maths的构造器带有参数,所有运行命令行时需要指定构造器参数值

> python maths.py pi 1000 --coeff=2
6.28127611241

如果不指定参数的值,运行时就会报错

> python maths.py pi 1000
Fire trace:
1. Initial component
2. ('The function received no value for the required argument:', 'coeff')
Type:        type
String form: <class '__main__.Maths'>
File:        ~/source/rollado/maths.py
Line:        5
Usage:       maths.py COEFF
             maths.py --coeff COEFF

如果改成暴露对象,那么放大系数就是在代码里写死的,无法在命令行进行参数定制了。这就是暴露对象和暴露类的差别,似乎暴露类在功能上更强大一些。

暴露属性

上面的所有例子我们最终暴露的都是函数,要么是模块里的函数,要么是类里的函数。但实际上fire还可以暴露属性,比如我们可以将上面的coeff参数通过命令行进行输出。

> python maths.py coeff --coeff=2
2
> python maths.py coeff --coeff=3
3

再来一个更加简单的例子

# example.py
import fire
english = 'Hello World'
spanish = 'Hola Mundo'
fire.Fire()

运行

$ python example.py english
Hello World
$ python example.py spanish
Hola Mundo

原理

640?wx_fmt=png

命令行中的参数顺序和代码内部对象的树状层次结构呈现一一对应关系。如果fire不带参数暴露了当前的模块,那么第一个参数就应该是这个模块内部的函数名、类名或者是变量名。如果第一个参数是函数,那么接下来的参数就是函数的参数。如果第一个参数是类,那么接下来的参数可能是这个类实例内部的方法或者字段。如果第一个参数是变量名,后面没有参数的话,就直接显示这个变量。如果后面还有参数,那么就把这个变量看成一个对象,然后继续使用后续参数来深入解析这个对象。

在Python里面所有的变量都是对象,包括普通的整数、字符串、浮点数、布尔值等。理论上可以一直将对象结构递归下去,形成一个复杂的链式调用。

链式暴露

接下来我们验证这个理论,尝试一下复杂的链式暴露。

import fire

class Chain(object):

    def __init__(self):
        self.value = 1

    def incr(self):
        print "incr", self.value
        self.value += 1
        return self

    def decr(self):
        print "decr", self.value
        self.value -= 1
        return self

    def get(self):
        return self.value

if __name__ == '__main__':
    fire.Fire(Chain)

运行一下

> python chains.py incr incr incr decr decr get
incr 1
incr 2
incr 3
decr 4
decr 3
2

Cool! 我们通过在每个方法里面方法self对象自身来实现了漂亮的链式调用效果。

接下来我们尝试对内置字符串对象进行解构

# xyz.py
import fire

value = "hello"

if __name__ == '__main__':
    fire.Fire()

字符串有upper和lower方法,我们反复使用upper和lower,然后观察结果

> python xyz.py value
hello
> python xyz.py value upper
HELLO
> python xyz.py value upper lower
Traceback (most recent call last):
  File "xyz.py", line 7, in <module>
    fire.Fire()
  File "/Users/pyloque/source/pys/.py/lib/python2.7/site-packages/fire/core.py", line 127, in Fire
    component_trace = _Fire(component, args, context, name)
  File "/Users/pyloque/source/pys/.py/lib/python2.7/site-packages/fire/core.py", line 366, in _Fire
    component, remaining_args)
  File "/Users/pyloque/source/pys/.py/lib/python2.7/site-packages/fire/core.py", line 542, in _CallCallable
    result = fn(*varargs, **kwargs)
TypeError: upper() takes no arguments (1 given)

很不幸,内置的字符串对象似乎不支持链式调用,第一个upper倒是执行成功了。不过fire提供了一个特殊的符号用来解决这个问题。

> python xyz.py value upper - lower
hello
> python xyz.py value upper - lower - upper
HELLO
> python xyz.py value upper - lower - upper - lower
hello

减号用来表示参数的结束,这样后续的参数就不会被当成函数的参数来映射了。

总结

有了Google Fire这样一个小巧的类库,我们就可以从复杂的命令行参数分析中解脱出来了。我们常说写代码要漂亮优雅,没有好的类库,这种理想也不是非常容易实现的。如果没有fire,你有本事试试把复杂的命令行参数解析代码写优雅了给老师我看看。

640?wx_fmt=jpeg

阅读更多高级文章,关注公众号「码洞」

MICCAI‘23 | TSegFormer:基于几何引导Transformer的口内扫描3D牙齿分割 光学口内扫描仪(IOS)在数字牙科中广泛应用于提供牙冠和牙龈的详细3D信息。准确的3D牙齿分割对于各种牙科应用至关重要,但现有方法在复杂边界处容易出错,并且在不同患者之间表现不佳。本文提出了TSegFormer,它通过多任务3D Transformer架构捕捉IOS点云中不同牙齿和牙龈之间的局部和全局依赖关系。此外,作者设计了一种基于新颖点曲率的几何引导损失,以端到端方式优化边界,避免了耗时的后处理,从而实现临床适用的分割。 阅读详情

相关推荐

百度api爬虫(1)从百度api中爬取地点数据

几句废话———— 百度api就是基于百度地图的开发接口,这么大的地图公司居然给开发接口真的很感激哎! 所以,言归正传。现在项目需求要把乌鲁木齐市内的所有清真寺都用矢量圈出来,然后做点统计啥的,最后做个专题图产品。 怎么把清真寺找出来? 领导的意思是你一个一个上网搜吧,这就是你的工作量。那我当然要想办法啊,边工作边学习工作才有意义嘛! 然后就发现百度api可以实现我的需求。其实可以通过py...

weixin_43105618的博客 8901

华为鸿蒙harmony4.0系统安装谷歌服务框架GMS谷歌应用商店Google Play(无需电脑操作,纯手机)

13. 打开安装的MicroG, 登录Google账号,完成后回到Googlefire,点击第二步,会让你登录你的第二个Google账户,如果需要的话就继续登录,以此类推,登录多个Google账号,需要提醒的是,Google账号只能这里登录,下面步骤不再允许登录账号。再安装Google play服务之前,会跳转“应用信息”,要求“强行停止”MicroG的运行,并点击“卸载”,完成之后才可继续安装。打开设置->系统和更新->日期和时间->关闭“自动设置”->将时间设置为2019年。下载安装包,链接私戳我发。

weixin_41710647的博客 1万+

手把手教你用U盘给海信IP501H刷机:GK6323V100C芯片的4.4.2和9.0固件实战

本文详细介绍了海信IP501H电视盒子基于GK6323V100C芯片的刷机实战指南,涵盖Android 4.4.2强刷和Android 9.0免拆刷机两种方案。从工具准备、短接操作到ADB调试,提供全流程解析和常见问题解决方案,帮助用户安全高效地完成刷机操作。

lemon的博客 1458

python工具是什么-使用Python编写命令行工具有什么好的库?

使用Python编写命令行工具的库很多,我最推荐的还是Google FireHello World要介绍Fire是什么,看一个简单的例子就明白了# calc.pyimport fireclass Calculator(object):"""A simple calculator class."""def double(self, numb...

weixin_37988176的博客 405

瑞芯微RK3576开发实战:固件烧录与内核启动的典型问题解析

本文详细解析了瑞芯微RK3576开发板在固件烧录与内核启动过程中遇到的典型问题及解决方案。从开发工具版本检查、DDR配置调整到内核启动异常的设备树适配和电源管理问题,提供了系统性的调试方法和实用技巧,帮助开发者高效解决RK3576开发中的常见挑战。

weixin_33700350的博客 455

GPD源码分析

gpd使用示例 先看下面一段代码,为标准gpd算法的使用方法,可以看到输入为点云,cloud_camera_; 输入:std::unique_ptr<gpd::util::Cloud> cloud_camera_ 输出: std::vector<std::unique_ptr<gpd::candidate::Hand>> grasps; // detect grasp poses gpd对象:std::unique_ptr<gpd::GraspDetect.

weixin_41003113的博客 2335

Python 笔记

Python 的运行环境(IDE)是IDLE GUI 在shell 里面运行。 Python中整数溢出的问题解决,计算结果后面有一个数字L可以用一个命令:type(object)来检测一个数是什么类型。e.g &gt;&gt;&gt; type(4)&lt;type 'int'&gt; #4是int,整数&gt;&gt;&gt; type(5.0)&lt;type 'float'&gt; #5.0...

gardenias_Lily 1406

SAP_PP模块定额工艺路线简介

在 SAP PP(生产计划)模块中,定额工艺路线(Routing) 是生产制造流程中的核心主数据之一,用于定义制造一个产品所需的标准操作步骤。工艺路线详细描述了生产过程中的各个工序、使用的工作中心、标准作业时间、资源分配等信息,是进行生产计划、成本核算、排产控制、车间执行等功能的基础。

我小时候很黑的博客 766

Google的Python开源Fire工具使用笔记

安装:pip install fire 编写程序测试: Windows CMD 测试:

xfyangle的博客 2621

基于改进YOLO11的天际线检测算法:复杂光照与恶劣天气适配实战

针对特定任务的YOLO改进,不应追求通用SOTA,而应深入理解任务的物理退化机理。Retinex对应光照模型、FAD对应散射模型、Wise-IoU对应边界不确定性——每个改进都有明确的物理解释,而非盲目的模块堆叠。时序一致性:引入轻量级RNN/Transformer模块利用视频帧间信息补偿单帧退化;多模态融合:结合红外/NIR波段穿透雾霾,与可见光特征在FAD-Neck中交叉注意力融合;自监督预训练:在海量无标注天际线视频上用MAE预训练Backbone,缓解恶劣天气标注稀缺问题。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 96

玩转Docker小游戏项目系列: Docker部署红心纸牌网页小游戏

玩转Docker小游戏项目系列: Docker部署红心纸牌网页小游戏

jks212454的博客 422

Google 开源的 Python 命令行库:fire 实现 git 命令

作者:HelloGitHub-Prodesire涉及的示例代码,已同步更新到HelloGitHub-Team仓库点击本文最下方的“阅读原文”即可获取一、前言在前面三篇介绍 fire ...

HelloGitHub 的博客 727

第八届传智杯微信小程序开发挑战赛练习题库

本文是微信小程序开发练习题库,包含单选题、多选题和判断题三种题型。单选题主要考察小程序开发基础知识,如数组方法、组件使用、API调用等;多选题涵盖样式属性、页面跳转、数据处理等综合知识;判断题则测试开发者对小程序特性、生命周期、功能限制等概念的理解。题目内容涉及小程序开发的各个方面,包括组件使用、API调用、数据绑定、页面配置等核心知识点,适合开发者进行自我测试和知识巩固。

qq_73044452的博客 506

探索 Python 的火种:Fire 库

在 Python 的世界中,库和框架的多样性是其强大功能和灵活性的体现。今天,我们将探索一个名为 Fire 的库,它不仅简单易用,还能极大提升开发效率。Fire 是 Google 开发的一个库,它允许你通过编写简单的命令行程序来处理复杂的任务。它的核心功能是将 Python 函数转换为命令行接口,从而使得命令行程序的编写变得异常简单。

AIGC搞起 1867

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

Google 开源的 Python 命令行库:初探 fire

作者:HelloGitHub-Prodesire涉及的示例代码,已同步更新到 HelloGitHub-Team 仓库点击本文最下方的“阅读原文”即可获取一、前言在本系列前面所有文章中,我...

HelloGitHub 的博客 783

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

Google 开源的 Python 命令行库:深入 fire(一)

作者:HelloGitHub-Prodesire涉及的示例代码,已同步更新到 HelloGitHub-Team 仓库点击本文最下方的“阅读原文”即可获取一、前言在第一篇“初探 fire”...

HelloGitHub 的博客 712

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

Python Fire 使用教程

简介 Fire是google开发的一个python第三方库,其作用是可以将python组件(函数调用,类调用)转换成命令行的形式去调用。 安装 可以直接使用pip来安装 pip install fire 或者可以从Fire源码安装,clole如下源码https://github.com/google/python-fire.git, 然后进入目录,运行如下命令 python setup.py i...

JohnSon 5216

Google 开源的 Python 命令行库:深入 fire(二)

作者:HelloGitHub-Prodesire涉及的示例代码,已同步更新到HelloGitHub-Team仓库点击本文最下方的“阅读原文”即可获取一、前言在上一篇文章中我们介绍了 ...

HelloGitHub 的博客 968

探索 Python 的火焰:Fire 库的神秘力量

在 Python 的世界中,命令行接口(CLI)的应用无处不在。但你是否曾因为编写繁琐的命令行参数解析代码而感到头疼?或者在寻找一种更简洁、更直观的方式来处理命令行参数?如果你的答案是肯定的,那么 Fire 库就是你的救星!Fire 是 Google 开发的一个 Python 库,它能够将任何 Python 函数转换为一个命令行接口。这意味着,你只需定义一个函数,Fire 就能自动为你生成相应的命令行工具。这不仅简化了代码,还提高了开发效率。

AIGC搞起 2182

Python 命令行工具:fire (已验证)

fire可以根据任何 Python 对象自动生成命令行接口。能以简单的方式生成 CLI是一个开发和调试 Python 代码的实用工具能将现存代码或别人的代码转换为 CLI使得在 Bash 和 Python 间的转换变得更容易通过预先为 REPL 设置所需的模块和变量,使得实用 REPL 更加容易。...

u010075995的博客 1826

一行命令实现功能?Google工程师是这样做的

最近想尝试将一些做过的小工具打包在一起,合成Python实用宝典的常用工具盒以分享给大家,这个工具盒功能非常强大,包括但不限于:一行命令提取音乐的高潮部分、一行命令人脸识别、一行命令分类文本…等等,敬请期待! 不过,做这样的工具盒其实原理不复杂,就是将用户需要用到的自定义参数通过命令直接传入Python中运行,用户不需要管代码、也不需要理解代码、直接使用。不过,做工具盒的时候却发现这样的问题,现在常用的命令行传参工具实在是不够用。 比如下面这个argparse的简单例子, 它使得Python命令在运行的时候

Python实用宝典网 837

Python Fire - 一个好用的命令行生成库

有没有这样一种感觉: 学了 Python,好歹也会一门语言了,偶尔想要自己写点小工具来用用,当代码写好后,怎么运行是个问题了。难道,每次要用的时候都要打开编码工具来运行? 写个带界面的?但是 UI 库都好难学,web 框架更难学。 那就写个命令行呗! 但是 Python 自带的命令行用起来并不方便。 现在有一个更简单方便的库,由 Google 开源的 fire库。 我们来学习一下怎么用。 首先...

小满测试 588

一个“牛逼”的 Python 命令行解析库-fire

在 Python 中,命令行解析库有非常多的选择方案,系统自带的 模块有 argparse,有 Flask 作者写的 click,但是 argparse 使用起来啰嗦, 要经历解析器初始化、参数定义、解析一套流程。例如: # -*- coding: utf-8 -*- # arg_test.py import argparse def counter(file_type=None): ...

Never-Giveup的博客 713
上一篇: Github上最受欢迎的Python框架Flask入门
下一篇: 知道Python语言的Google Fire项目么,我将它移植到了Java上
codehole_
博客等级 码龄7年 34粉丝 132原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值