用google/python-fire代替argparse
Published on
Table of Contents
最近从argparse迁移到fire,fire在某些方面比argparse更简洁。这篇文章总结了fire的核心概念和使用技巧。
fire和argparse核心差异 Link to this section
fire的核心理念是任何Python对象都能变成CLI,大部分情况下只需写普通Python函数或类,fire会自动处理CLI部分。
argparse思维模式 Link to this section
python
# argparse: 显式定义每个参数
parser = argparse.ArgumentParser()
parser.add_argument('--name', type=str, help='Your name')
parser.add_argument('--count', type=int, default=1)
args = parser.parse_args()fire思维模式 Link to this section
python
# fire: 从函数签名自动推导
import fire
def main(name, count=1):
print(f"Hello {name}! " * count)
if __name__ == "__main__":
fire.Fire(main)快速精通fire Link to this section
一个最简单例子 Link to this section
python
import fire
# 最简单的 CLI
def main(name):
print(f"Hello {name}")
fire.Fire(main)理解参数类型转换 Link to this section
python
# fire 自动转换类型
def main(
name, # 字符串参数
age=18, # 整数参数,默认值
verbose=False, # 布尔参数
items=None # 可以传列表 --items=[a,b,c]
):
pass子命令模式(使用类或字典) Link to this section
python
import fire
class Calculator:
def add(self, x, y):
"""Add two numbers"""
return x + y
def multiply(self, x, y):
"""Multiply two numbers"""
return x * y
if __name__ == "__main__":
fire.Fire(Calculator)或者使用字典:
python
def add(x, y):
return x + y
def multiply(x, y):
return x * y
if __name__ == "__main__":
fire.Fire({
'add': add,
'multiply': multiply
})从argparse迁移到fire Link to this section
argparse版本 Link to this section
python
parser = argparse.ArgumentParser()
parser.add_argument('input_file')
parser.add_argument('--output', '-o', default='output.txt')
parser.add_argument('--verbose', '-v', action='store_true')
parser.add_argument('--count', type=int, default=1)
args = parser.parse_args()fire等效版本 Link to this section
python
import fire
def main(input_file, output='output.txt', verbose=False, count=1):
pass
if __name__ == "__main__":
fire.Fire(main)常见问题和解决方案 Link to this section
位置参数vs关键字参数 Link to this section
python
# 可以混合使用位置参数和关键字参数
def process(input_file, output_dir, verbose=False):
pass
# 调用方式:
# python script.py input.txt /tmp/output --verbose
# python script.py input.txt /tmp/output --verbose=True布尔参数的处理 Link to this section
python
def main(verbose=False):
pass
# 使用方式:
# --verbose # True
# --verbose=True # True
# --verbose=False # False
# --noverbose # False列表和字典参数 Link to this section
python
def main(items=None, config=None):
pass
# 调用方式:
# --items=[1,2,3]
# --items='[a,b,c]'
# --config='{"key": "value"}'链式调用 Link to this section
python
class Pipeline:
def load(self, filename):
self.data = open(filename).read()
return self
def process(self):
self.data = self.data.upper()
return self
def save(self, filename):
open(filename, 'w').write(self.data)
# 调用: python script.py load input.txt process save output.txtfire的优势和局限 Link to this section
优势 Link to this section
极简代码:几乎零样板代码
自动类型转换:智能解析字符串为Python对象
交互模式:支持
– –interactive进入Python REPL自动帮助:
– –help自动生成文档
局限 Link to this section
类型提示不强制:fire不依赖类型注解,可能导致运行时错误
参数验证较弱:需要手动验证复杂约束
帮助信息简单:不如argparse详细
调试困难:复杂的嵌套调用可能难以理解
额外开销 Link to this section
fire的启动开销很小,主要来自:
函数签名检查(使用inspect模块)
参数解析和类型推导
相比argparse,fire的启动速度相当,甚至在简单场景下更快。