Sometimes we have a need:
We define a Python method that takes arguments but wants to expose them on the command line when called.
For example, here is a crawl method:
import requests
def scrape(url, timeout=10) :
response = requests.get(url, timeout=timeout)
print(response.text)
Copy the code
Here a scrape method is defined where the first parameter receives the URL, which is the url to crawl, and the second parameter receives timeout, which specifies the timeout time.
We might call it like this:
scrape('https:///www.baidu.com'.10)
Copy the code
If we want to change the parameter to change the URL, we have to change the code.
Sometimes we want to expose these parameters on the command line. In this case, we might use argparse and other libraries to declare what each parameter does one by one. This is very tedious.
parser = argparse.ArgumentParser(description='Scrape Function')
parser.add_argument('url'.type=str.help='an integer for the accumulator')
parser.add_argument('timeout'.type=int.help='sum the integers (default: find the max)')
if __name__ == '__main__':
args = parser.parse_args()
scrape(args.url, args.timeout)
Copy the code
So we can call the script smoothly from the command line:
python3 main.py https://www.baidu.com 10
Copy the code
Does it feel like a hassle? Argparse is smelly and long to write, and it’s hard to think about.
Fire
But let’s introduce a library that can do this with just two lines of code.
This library, called Fire, can quickly add command-line argument support to a Python method or class.
First look at the installation method, using PIP3 installation can be:
pip3 install fire
Copy the code
So we’re set up.
use
Let’s look at some examples.
Method supports
The first code example is as follows:
import fire
def hello(name="World") :
return "Hello %s!" % name
if __name__ == '__main__':
fire.Fire(hello)
Copy the code
Here we define a hello method, take a name argument, World by default, and output the string Hello plus name.
And then we import the fire library, call its fire method and pass in the hello method declaration, what happens?
Let’s save this code as demo1.py and run it using Python3:
python3 demo1.py
Copy the code
The running results are as follows:
Hello World!
Copy the code
It doesn’t seem that different.
But if we run the following command, we can see something amazing:
python3 demo1.py --help
Copy the code
The running results are as follows:
NAME
demo1.py
SYNOPSIS
demo1.py <flags>
FLAGS
--name=NAME
Default: 'World'
Copy the code
As you can see, it turns the name argument into an optional argument on the command line, and we can replace the name argument with — name.
Let’s try it:
python3 demo1.py --name 123
Copy the code
Here we pass in a name parameter of 123, and we see that the result is as follows:
Hello 123!
Copy the code
Is it very convenient? We can easily support and replace command-line arguments without argparse.
What if we unset the name parameter by default? The code rewrite is as follows:
import fire
def hello(name) :
return "Hello %s!" % name
if __name__ == '__main__':
fire.Fire(hello)
Copy the code
Rerun at this point:
python3 demo1.py --help
Copy the code
The result should look like this:
NAME
demo1.py
SYNOPSIS
demo1.py NAME
POSITIONAL ARGUMENTS
NAME
NOTES
You can also use flags syntax for POSITIONAL ARGUMENTS
Copy the code
The name parameter becomes mandatory. We must specify this parameter on the command line, and the call will look like this:
python3 demo1.py 123
Copy the code
The result is the same.
Class supports
Of course, the fire library does not only support adding command line support to methods, but also to classes.
Here’s another example:
import fire
class Calculator(object) :
def double(self, number) :
return 2 * number
if __name__ == '__main__':
fire.Fire(Calculator)
Copy the code
Let’s save this code as demo2.py and run:
python3 demo2.py
Copy the code
The running results are as follows:
NAME
demo2.py
SYNOPSIS
demo2.py COMMAND
COMMANDS
COMMAND is one of the following:
double
Copy the code
As you can see, here it identifies the methods in the Calculator class, and one of the commands is double, so let’s try calling:
python3 demo2.py double
Copy the code
The running results are as follows:
ERROR: The function received no value for the required argument: number
Usage: demo2.py double NUMBER
For detailed information on this command, run:
demo2.py double --help
Copy the code
Here we say that we must specify another parameter, called NUMBER, which is also required, so let’s try adding:
python3 demo2.py double 4
Copy the code
The running results are as follows:
8
Copy the code
At this point the correct result can be achieved.
So, taken together, fire can be a class command line, with each command corresponding to a method name and additional optional or required arguments added to the end of the command line arguments.
rewrite
Finally, let’s go back and add command-line argument support to the scrape method we defined in the beginning:
import requests
import fire
def scrape(url, timeout=10) :
response = requests.get(url, timeout=timeout)
print(response.text)
if __name__ == '__main__':
fire.Fire(scrape)
Copy the code
That’s it! Isn’t it convenient to omit the verbose argparse code?
The call looks like this:
NAME
main.py
SYNOPSIS
main.py URL <flags>
POSITIONAL ARGUMENTS
URL
FLAGS
--timeout=TIMEOUT
Default: 10
Copy the code
URL is mandatory and timeout is optional.
Finally call:
python3 main.py https://www.baidu.com
Copy the code
This makes it easy to pass the URL through the command line.
Of course, timeout is optional. We can specify the timeout argument with — timeout:
python3 main.py https://www.baidu.com --timeout 5
Copy the code
Then both parameters can be successfully assigned, the final effect is to climb baidu, 5 seconds timeout.
How’s that? Is it convenient? Use it, everyone!
For more exciting content, please pay attention to my public account “Attack Coder” and “Cui Qingcai | Jingmi”.