Using the Python Fire Library to Build Simple Command-Line Interfaces
This article explains why the Fire library is a superior alternative to argparse and Click for creating Python command-line tools, demonstrates its installation, provides multiple usage patterns—including exposing functions, classes, and dictionaries as CLIs—and showcases advanced features such as command grouping, attribute access, and custom argument handling.
Why Use Fire
When building command-line tools in Python, the built‑in argparse module can become verbose and unwieldy, while click adds complexity for larger scripts. The fire library generates CLIs automatically with just two lines of code, making it faster and more readable.
Installation
<code># pip
pip3 install fire
# conda
conda install fire -c conda-forge
# source
python3 setup.py install</code>Basic Usage
Expose a function as a CLI:
<code>import fire
def hello(name):
return 'Hello {name}!'.format(name=name)
if __name__ == '__main__':
fire.Fire()</code>Run with:
<code>$ python example.py hello World
Hello World!</code>Expose a specific function:
<code>import fire
def hello(name):
return 'Hello {name}!'.format(name=name)
if __name__ == '__main__':
fire.Fire(hello)</code>Run with:
<code>$ python example.py World
Hello World!</code>Multiple Commands
Bind all functions automatically:
<code>import fire
def add(x, y):
return x + y
def multiply(x, y):
return x * y
if __name__ == '__main__':
fire.Fire()</code>Or provide a dictionary for custom command names:
<code>import fire
def add(x, y):
return x + y
def multiply(x, y):
return x * y
if __name__ == '__main__':
fire.Fire({'add': add, 'multiply': multiply})</code>Advanced Features
Command grouping with classes:
<code>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()
return 'Pipeline complete'
if __name__ == '__main__':
fire.Fire(Pipeline)</code>Accessing attributes directly:
<code>class Airport(object):
def __init__(self, code):
self.code = code
self.name = dict(airports).get(self.code)
self.city = self.name.split(',')[0] if self.name else None
if __name__ == '__main__':
fire.Fire(Airport)</code>Custom callbacks and argument parsing are also supported, allowing automatic type inference and flexible separators.
Python Programming Learning Circle
A global community of Chinese Python developers offering technical articles, columns, original video tutorials, and problem sets. Topics include web full‑stack development, web scraping, data analysis, natural language processing, image processing, machine learning, automated testing, DevOps automation, and big data.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.