python-fire的使用
来源:互联网 发布:mac air输入法怎么切换 编辑:程序博客网 时间:2024/06/06 14:29
本文完全转载自:https://github.com/google/python-fire/blob/master/docs/guide.md#version-3-firefireobject
fire简单参考实例:http://blog.csdn.net/u010099080/article/details/70332074
The Python Fire Guide
Introduction
Welcome to the Python Fire guide! Python Fire is a Python library that will turnany Python component into a command line interface with just a single call toFire
.
Let's get started!
Installation
To install Python Fire from pypi, run:
pip install fire
Alternatively, to install Python Fire from source, clone the source and run:
python setup.py install
Hello World
Version 1:fire.Fire()
The easiest way to use Fire is to take any Python program, and then simply callfire.Fire()
at the end of the program. This will expose the full contents ofthe program to the command line.
import firedef hello(name): return 'Hello {name}!'.format(name=name)if __name__ == '__main__': fire.Fire()
Here's how we can run our program from the command line:
$ python example.py hello WorldHello World!
Version 2:fire.Fire(<fn>)
Let's modify our program slightly to only expose the hello
function to thecommand line.
import firedef hello(name): return 'Hello {name}!'.format(name=name)if __name__ == '__main__': fire.Fire(hello)
Here's how we can run this from the command line:
$ python example.py WorldHello World!
Notice we no longer have to specify to run the hello
function, because wecalledfire.Fire(hello)
.
Version 3: Using a main
We can alternatively write this program like this:
import firedef hello(name): return 'Hello {name}!'.format(name=name)def main(): fire.Fire(hello)if __name__ == '__main__': main()
Or if we're usingentry points,then simply this:
import firedef hello(name): return 'Hello {name}!'.format(name=name)def main(): fire.Fire(hello)
Exposing Multiple Commands
In the previous example, we exposed a single function to the command line. Nowwe'll look at ways of exposing multiple functions to the command line.
Version 1:fire.Fire()
The simplest way to expose multiple commands is to write multiple functions, andthen call Fire.
import firedef add(x, y): return x + ydef multiply(x, y): return x * yif __name__ == '__main__': fire.Fire()
We can use this like so:
$ python example.py add 10 2030$ python example.py multiply 10 20200
You'll notice that Fire correctly parsed 10
and 20
as numbers, rather thanas strings. Read more aboutargument parsing here.
Version 2:fire.Fire(<dict>)
In version 1 we exposed all the program's functionality to the command line. Byusing a dict, we can selectively expose functions to the command line.
import firedef add(x, y): return x + ydef multiply(x, y): return x * yif __name__ == '__main__': fire.Fire({ 'add': add, 'multiply': multiply, })
We can use this in the same way as before:
$ python example.py add 10 2030$ python example.py multiply 10 20200
Version 3:fire.Fire(<object>)
Fire also works on objects, as in this variant. This is a good way to exposemultiple commands.
import fireclass Calculator(object): def add(self, x, y): return x + y def multiply(self, x, y): return x * yif __name__ == '__main__': calculator = Calculator() fire.Fire(calculator)
We can use this in the same way as before:
$ python example.py add 10 2030$ python example.py multiply 10 20200
Version 4:fire.Fire(<class>)
Fire also works on classes. This is another good way to expose multiplecommands.
import fireclass Calculator(object): def add(self, x, y): return x + y def multiply(self, x, y): return x * yif __name__ == '__main__': fire.Fire(Calculator)
We can use this in the same way as before:
$ python example.py add 10 2030$ python example.py multiply 10 20200
Why might you prefer a class over an object? One reason is that you can passarguments for constructing the class too, as in this broken calculator example.
import fireclass 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._offsetif __name__ == '__main__': fire.Fire(BrokenCalculator)
When you use a broken calculator, you get wrong answers:
$ python example.py add 10 2031$ python example.py multiply 10 20201
But you can always fix it:
$ python example.py add 10 20 --offset=030$ python example.py multiply 10 20 --offset=0200
Unlike calling ordinary functions, which can be done both with positionalarguments and named arguments (--flag syntax), arguments to __init__functions must be passed with the --flag syntax. See the section oncalling functions for more.
Grouping Commands
Here's an example of how you might make a command line interface with groupedcommands.
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)
Here's how this looks at the command line:
$ python example.py runIngesting! Nom nom nom...Burp!$ python example.py ingestion runIngesting! Nom nom nom...$ python example.py digestion runBurp!$ python example.py digestion statusSatiated.
You can nest your commands in arbitrarily complex ways, if you're feeling grumpyor adventurous.
Accessing Properties
In the examples we've looked at so far, our invocations of python example.py
have all run some function from the example program. In this example, we simplyaccess a property.
from airports import airportsimport fireclass 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 Noneif __name__ == '__main__': fire.Fire(Airport)
Now we can use this program to learn about airport codes!
$ python example.py --code=JFK codeJFK$ python example.py --code=SJC nameSan Jose-Sunnyvale-Santa Clara, CA - Norman Y. Mineta San Jose International (SJC)$ python example.py --code=ALB cityAlbany-Schenectady-Troy
By the way, you can find thisairports module here.
Chaining Function Calls
When you run a Fire CLI, you can take all the same actions on the result ofthe call to Fire that you can take on the original object passed in.
For example, we can use our Airport CLI from the previous example like this:
$ python example.py --code=ALB city upperALBANY-SCHENECTADY-TROY
This works since upper
is a method on all strings.
So, if you want to set up your functions to chain nicely, all you have to do ishave a class whose methods return self. Here's an example.
import fireclass BinaryCanvas(object): """A canvas with which to make binary art, one bit at a time.""" def __init__(self, size=10): self.pixels = [[0] * size for _ in range(size)] self._size = size self._row = 0 # The row of the cursor. self._col = 0 # The column of the cursor. def __str__(self): return '\n'.join(' '.join(str(pixel) for pixel in row) for row in self.pixels) def show(self): print(self) return self def move(self, row, col): self._row = row % self._size self._col = col % self._size return self def on(self): return self.set(1) def off(self): return self.set(0) def set(self, value): self.pixels[self._row][self._col] = value return selfif __name__ == '__main__': fire.Fire(BinaryCanvas)
Now we can draw stuff :).
$ python example.py move 3 3 on move 3 6 on move 6 3 on move 6 6 on move 7 4 on move 7 5 on __str__0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 00 0 0 1 0 0 1 0 0 00 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 00 0 0 1 0 0 1 0 0 00 0 0 0 1 1 0 0 0 00 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0
It's supposed to be a smiley face.
Can we make an even simpler example than Hello World?
Yes, this program is even simpler than our original Hello World example.
import fireenglish = 'Hello World'spanish = 'Hola Mundo'fire.Fire()
You can use it like this:
$ python example.py englishHello World$ python example.py spanishHola Mundo
Calling Functions
Arguments to a constructor are passed by name using flag syntax --name=value
.
For example, consider this simple class:
import fireclass Building(object): def __init__(self, name, stories=1): self.name = name self.stories = 1 def climb_stairs(self, stairs_per_story=10): for story in range(self.stories): for stair in range(1, stairs_per_story): yield stair yield 'Phew!' yield 'Done!'if __name__ == '__main__': fire.Fire(Building)
We can instantiate it as follows: python example.py --name="Sherrerd Hall"
Arguments to other functions may be passed positionally or by name using flagsyntax.
To instantiate a Building
and then run the climb_stairs
function, thefollowing commands are all valid:
$ python example.py --name="Sherrerd Hall" --stories=3 climb_stairs 10$ python example.py --name="Sherrerd Hall" climb_stairs --stairs_per_story=10$ python example.py --name="Sherrerd Hall" climb_stairs --stairs-per-story 10$ python example.py climb-stairs --stairs-per-story 10 --name="Sherrerd Hall"
You'll notice that hyphens and underscores (-
and _
) are interchangeable inmember names and flag names.
You'll also notice that the constructor's arguments can come after thefunction's arguments or before the function.
You'll also notice that the equal sign between the flag name and its value isoptional.
Functions with*varargs
and **kwargs
Fire supports functions that take *varargs or **kwargs. Here's an example:
import firedef order_by_length(*items): """Orders items by length, breaking ties alphabetically.""" sorted_items = sorted(items, key=lambda item: (len(str(item)), str(item))) return ' '.join(sorted_items)if __name__ == '__main__': fire.Fire(order_by_length)
To use it, we run:
$ python example.py dog cat elephantcat dog elephant
You can use a separator to indicate that you're done providing arguments to afunction. All arguments after the separator will be used to process the resultof the function, rather than being passed to the function itself. The defaultseparator is the hyphen-
.
Here's an example where we use a separator.
$ python example.py dog cat elephant - upperCAT DOG ELEPHANT
Without the separator, upper would have been treated as another argument.
$ python example.py dog cat elephant uppercat dog upper elephant
You can change the separator with the --separator
flag. Flags are alwaysseparated from your Fire command by an isolated--
. Here's an example where wechange the separator.
$ python example.py dog cat elephant X upper -- --separator=XCAT DOG ELEPHANT
Separators can be useful when a function accepts *varargs, **kwargs, ordefault values that you don't want to specify. It is also important to rememberto change the separator if you want to pass-
as an argument.
Argument Parsing
The types of the arguments are determined by their values, rather than by thefunction signature where they're used. You can pass any Python literal from thecommand line: numbers, strings, tuples, lists, dictionaries, (sets are onlysupported in some versions of Python). You can also nest the collectionsarbitrarily as long as they only contain literals.
To demonstrate this, we'll make a small example program that tells us the typeof any argument we give it:
import firefire.Fire(lambda obj: type(obj).__name__)
And we'll use it like so:
$ python example.py 10int$ python example.py 10.0float$ python example.py hellostr$ python example.py '(1,2)'tuple$ python example.py [1,2]list$ python example.py Truebool$ python example.py {name: David}dict
You'll notice in that last example that bare-words are automatically replacedwith strings.
Be careful with your quotes! If you want to pass the string "10"
, rather thanthe int10
, you'll need to either escape or quote your quotes. Otherwise Bashwill eat your quotes and pass an unquoted10
to your Python program, whereFire will interpret it as a number.
$ python example.py 10int$ python example.py "10"int$ python example.py '"10"'str$ python example.py "'10'"str$ python example.py \"10\"str
Be careful with your quotes! Remember that Bash processes your arguments first,and then Fire parses the result of that.If you wanted to pass the dict{"name": "David Bieber"}
to your program, youmight try this:
$ python example.py '{"name": "David Bieber"}' # Good! Do this.dict$ python example.py {"name":'"David Bieber"'} # Okay.dict$ python example.py {"name":"David Bieber"} # Wrong. This is parsed as a string.str$ python example.py {"name": "David Bieber"} # Wrong. This isn't even treated as a single argument.<error>$ python example.py '{"name": "Justin Bieber"}' # Wrong. This is not the Bieber you're looking for. (The syntax is fine though :))dict
Boolean Arguments
The tokens True
and False
are parsed as boolean values.
You may also specify booleans via flag syntax --name
and --noname
, which setname
toTrue
and False
respectively.
Continuing the previous example, we could run any of the following:
$ python example.py --obj=Truebool$ python example.py --obj=Falsebool$ python example.py --objbool$ python example.py --noobjbool
Be careful with boolean flags! If a token other than another flag immediatelyfollows a flag that's supposed to be a boolean, the flag will take on the valueof the token rather than the boolean value. You can resolve this: by putting aseparator after your last flag, by explicitly stating the value of the booleanflag (as in --obj=True
), or by making sure there's another flag after anyboolean flag argument.
Using Fire Flags
Fire CLIs all come with a number of flags. These flags should be separated fromthe Fire command by an isolated--
. If there is at least one isolated --
argument, then arguments after the final isolated--
are treated as flags,whereas all arguments before the final isolated--
are considered part of theFire command.
One useful flag is the --interactive
flag. Use the --interactive
flag on anyCLI to enter a Python REPL with all the modules and variables used in thecontext whereFire
was called already available to you for use. Other usefulvariables, such as the result of the Fire command will also be available. Usethis feature like this:python example.py -- --interactive
.
You can add the help flag to any command to see help and usage information. Fireincorporates your docstrings into the help and usage information that itgenerates. Fire will try to provide help even if you omit the isolated--
separating the flags from the Fire command, but may not always be able to, sincehelp
is a valid argument name. Use this feature like this:python example.py -- --help
.
The complete set of flags available is shown below, in the reference section.
Reference
pip install fire
Creating a CLI
import fire
Callfire.Fire()
Turns the current module into a Fire CLI.Callfire.Fire(component)
Turns component
into a Fire CLI.Flags
command -- --help
Show help and usage information for the command.REPLcommand -- --interactive
Enter interactive mode.Separatorcommand -- --separator=X
This sets the separator to X
. The default separator is-
.Completioncommand -- --completion
Generate a completion script for the CLI.Tracecommand -- --trace
Gets a Fire trace for the command.Verbosecommand -- --verbose
Include private members in the output.Note that flags are separated from the Fire command by an isolated --
arg.
Disclaimer
Python Fire is not an official Google product.
- python-fire的使用
- Google的Python开源Fire工具使用笔记
- 火狐浏览器(fire bug)的使用:
- Fire Net problem Python
- ZJU 1002 Fire Net (Python)
- Fire!
- Fire!
- Fire!
- Fire!
- Fire
- Fire!
- Fire!
- Fire
- Python Fire开源—用于自动生成命令行界面的内容库
- FIRE FOX 的一些插件
- Kindle Fire的电子书之外
- Kindle fire HD 使用 亚马逊原生应用
- NanoPi 2 Fire 连接使用USB WiFi
- java爬取新浪微博带有“展开全文”的完整微博文本
- ContextLoaderListener作用详解
- 等高布局
- 图解SQL的各种连接join
- 生成图形验证码
- python-fire的使用
- 求输入几个数的平均值
- 用程序算出几个数的平均值
- Spring框架中的定时器 如何使用和配置
- centos 7管理命令整合经典
- Spring IOC
- JS——继承(创建共有属性和方法)
- spring IOC 概述
- 使用expdp导出A用户的数据后使用impdpd导入到B用户中