Prodesire

The sample code and history articles involved have been synchronized to the HelloGithub-Team repository

One, foreword

In our first “Fire Primer,” we took a first look at the simple steps to use fire and learned how to use it Pythonic.

Today we’ll take a closer look at fire’s subcommands, nested commands, and property access capabilities.

This series of articles uses Python 3 as the interpreter by default. If you are still using Python 2, be aware of the differences in syntax and library usageCopy the code

Second, the function of

2.1 the son command

There are several ways to implement subcommands using fire:

2.1.1 Define some functions using fire.fire ()

The simplest way to implement a subcommand is to define several functions, each of which is implicitly a subcommand name, and then call fire.fire () to parse all functions in the current module into handlers for the corresponding subcommand.

import fire

def add(x, y):
  return x + y

def multiply(x, y):
  return x * y

if __name__ == '__main__':
  fire.Fire()
Copy the code

We can then call it from the command line like this:

$ python example.py add 10 20
30
$ python example.py multiply 10 20
200
Copy the code

How to identify parameter types, such as add 10 and 20 as numbers rather than strings, will be explained in the parameter parsing section of the next article.

2.1.2 Define some functions using fire.fire ()

In version 2.1.1, all functions are treated as subcommands. Sometimes we just want to treat part of a function as a subcommand, or we want the subcommand name to be different from the function name. At this point we can explicitly tell the fire through the dictionary object.

The dictionary object is of the form {‘ subcommand name ‘: function}. For example, in the previous example, we wanted the final subcommands to be add and mul, so we could write:

fire.Fire({
  'add': add,
  'mul': multiply,
})
Copy the code

We can then call it from the command line like this:

$ python example.py add 10 20
30
$ python example.py mul 10 20
200
Copy the code

2.1.3 Define classes and methods using fire.fire ()

Classes and methods are defined in much the same way as functions are defined in the last article, except that they are organized in terms of classes.

The class is then instantiated and the instantiated object is mostly fire.Fire:

import fire

class Calculator(object):

  def add(self, x, y):
    return x + y

  def multiply(self, x, y):
    return x * y

if __name__ == '__main__':
  calculator = Calculator()
  fire.Fire(calculator)
Copy the code

2.1.4 Define classes and methods using fire.fire ()

The only difference from 2.1.3 is that we use a class instead of an instance object as an entry to fire.Fire:

fire.Fire(Calculator)
Copy the code

The basic function of the pass class is the same as that of the instance object, but the pass class has an additional feature: if parameters are defined in the constructor, they are used as option parameters for the entire command line program.

import fire

class BrokenCalculator(object):

  def __init__(self, offset=1):
      self._offset = offset

  def add(self, x, y):
    return x + y + self._offset

  def multiply(self, x, y):
    return x * y + self._offset

if __name__ == '__main__':
  fire.Fire(BrokenCalculator)
Copy the code

The help commands are as follows:

$ python example.py --help
INFO: Showing help with the command 'example.py -- --help'.

NAME
    example.py

SYNOPSIS
    example.py <flags>

FLAGS
    --offset=OFFSET
Copy the code

This shows that the offset in the constructor brokencalculator.__init__ (self, offset=1) is automatically converted to the global option argument –offset on the command line, with a default value of 1.

We can call this from the command line:

$ python example.py add 10 20
31
$ python example.py multiply 10 20
201
$ python example.py add 10 20 --offset=0
30
$ python example.py multiply 10 20 --offset=0
200
Copy the code

2.2 Command Group/Nested Commands

To implement nested commands, organize multiple classes as shown in the following example:

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()

if __name__ == '__main__':
  fire.Fire(Pipeline)
Copy the code

In the example above:

  • IngestionStageSubcommands are implementedrun
  • DigestionStageSubcommands are implementedrunstatus
  • PipelineIn the constructor ofIngestionStageInstantiated asingestionThat will beDigestionStageInstantiated asdigestion, put these two in a command group, thus supporting:
    • ingestion run
    • digestion run
    • digestion status
  • PipelineSubcommands are implementedrun

Therefore, the entire command line program supports the following commands:

  • run
  • ingestion run
  • digestion run
  • digestion status

We can then call it from the command line like this:

$ python example.py run
Ingesting! Nom nom nom...
Burp!
$ python example.py ingestion run
Ingesting! Nom nom nom...
$ python example.py digestion run
Burp!
$ python example.py digestion status
Satiated.
Copy the code

2.3 Attribute Access

Property access is a unique feature of Fire compared to other command line libraries. The access attribute is to get the value of the preset attribute.

For example, you specify –code on the command line to tell the program what code to query for, and then you want to return the zipcode via the zipcode attribute and the city name via the city attribute. Properties can then be implemented as instance member properties:

import fire

cities = {
  'hz': (310000.'hangzhou'),
  'bj': (100000.'Beijing'),}class City(object):

  def __init__(self, code):
    info = cities.get(code)
    self.zipcode = info[0] if info else None
    self.city = info[1] if info else None

if __name__ == '__main__':
  fire.Fire(City)
Copy the code

The usage is as follows:

$python example.py --code bj zipcode 100000 $python example.py --code Hz cityCopy the code

Third, summary

Not only is implementing subcommands and nested commands with Fire much simpler and cleaner than other command line libraries, but fire also provides the unique ability to access properties.

In the next article, we’ll take a closer look at Fire and introduce more advanced features like chained function calls, custom serialization, parameter parsing, fire options, and more.


“Explain Open Source Project series” — let the people who are interested in open source projects not be afraid, let the initiator of open source projects not be alone. Follow along as you discover the joys of programming, use, and how easy it is to get involved in open source projects. Welcome to leave a message to contact us, join us, let more people fall in love with open source, contribute to open source ~