Python?Fire實(shí)現(xiàn)自動生成命令行接口
命令行程序是平時寫一些小工具時最常用的方式。
為了讓命令行程序更加靈活,我們常常會設(shè)置一些參數(shù),根據(jù)參數(shù)讓程序執(zhí)行不同的功能。
這樣就不用頻繁的修改代碼來執(zhí)行不同的功能。
隨著命令行程序功能的豐富,也就是參數(shù)多了以后,解析和管理參數(shù)之間的關(guān)系會變得越來越繁重。
而本次介紹的 Fire
庫,正好可以解決這個問題。
使用 Fire
庫,我們只要關(guān)心具體功能的實(shí)現(xiàn),最后Fire
會幫助我們自動把所有功能組織成一個命令行程序。
Fire
庫在github上的地址:github.com/google/python-fire
1. 一般命令
一般的命令,也就是帶有幾個參數(shù)的一段程序,比如:
# -*- coding:utf-8 -*- def import_file(fp): print("import file from: {}".format(fp)) def export_file(fp): print("EXPORT file to: {}".format(fp))
這是模擬文件導(dǎo)出功能的兩個函數(shù)。
使用 Fire
轉(zhuǎn)換成命令行程序非常簡單,下面介紹幾種常用的方式。
1.1. 默認(rèn)方式
# -*- coding:utf-8 -*- import fire def import_file(fp): print("IMPORT file from: {}".format(fp)) def export_file(fp): print("EXPORT file to: {}".format(fp)) if __name__ == "__main__": # fire默認(rèn)會將所有函數(shù)轉(zhuǎn)換成子命令 fire.Fire()
然后,就可以通過子命令的方式執(zhí)行導(dǎo)入導(dǎo)出功能。
$ python main.py import_file --fp ./path/xxx.csv IMPORT file from: ./path/xxx.csv $ python main.py export_file --fp ./path/xxx.csv EXPORT file to: ./path/xxx.csv
函數(shù)的名稱自動變?yōu)?strong>子命令的名稱,函數(shù)的參數(shù)自動變成子命令的參數(shù)。
1.2. Fire<fn>
Fire
庫的默認(rèn)方式會把所有的函數(shù)都轉(zhuǎn)換為子命令,如果只想導(dǎo)出一個函數(shù)的話,可以用 Fire<fn>
的方式。
if __name__ == "__main__": # 只導(dǎo)出 import_file 函數(shù)作為子命令 fire.Fire(import_file)
只導(dǎo)出一個函數(shù)的時候,執(zhí)行命令的時候不需要輸入子命令的名稱。
$ python main.py --fp ./path/xxx.csv
IMPORT file from: ./path/xxx.csv
1.3. Fire<dict>
導(dǎo)出多個函數(shù)作為子命令時,默認(rèn)是使用函數(shù)名作為子命令名稱的,函數(shù)名稱有時候會非常長,輸入很麻煩。
這時,可以用 Fire<dict>
方式。
if __name__ == "__main__": # 子命令的名稱分別是:import 和 export fire.Fire({ "import": import_file, "export": export_file, })
執(zhí)行時,使用簡化的子命令名稱。
$ python main.py import --fp ./path/xxx.csv
IMPORT file from: ./path/xxx.csv
$ python main.py export --fp ./path/xxx.csv
EXPORT file to: ./path/xxx.csv
這種方式非常靈活,不僅可以設(shè)置子命令名稱,還可以控制需要導(dǎo)出哪些函數(shù)。
1.4. Fire<object>
除了導(dǎo)出函數(shù),Fire<object>
方式也可以導(dǎo)出對象的公有方法。
import fire class FileHandler(): def __init__(self): pass def import_file(self, fp): print("IMPORT file from: {}".format(fp)) def export_file(self, fp): print("EXPORT file to: {}".format(fp)) if __name__ == "__main__": fh = FileHandler() fire.Fire(fh)
使用方式如下:
$ python main.py import_file --fp ./path/xxx.csv
IMPORT file from: ./path/xxx.csv
$ python main.py export_file --fp ./path/xxx.csv
EXPORT file to: ./path/xxx.csv
使用對象的方式?jīng)]有直接使用函數(shù)那么簡單,但有個好處是可以在初始化時傳入一些狀態(tài)。
import fire import os class FileHandler(): def __init__(self, folder=""): self.folder = folder def import_file(self, fp): print("IMPORT file from: {}".format(os.path.join(self.folder, fp))) def export_file(self, fp): print("EXPORT file to: {}".format(os.path.join(self.folder, fp))) if __name__ == "__main__": # 設(shè)置了默認(rèn)文件夾,使用時直接傳入文件名即可 fh = FileHandler("./default_path") fire.Fire(fh)
$ python main.py import_file --fp xxx.csv
IMPORT file from: ./default_path/xxx.csv
$ python main.py export_file --fp xxx.csv
EXPORT file to: ./default_path/xxx.csv
1.5. Fire<class>
Fire<class>
的方式也可以直接作用在類上,不用初始化對象。
if __name__ == "__main__": fire.Fire(FileHandler)
和 Fire<object>
不同的是,__init__
方法的參數(shù)也變成了命令的參數(shù),也可以在命令行中調(diào)整了。
$ python main.py import_file --fp xxx.csv
IMPORT file from: xxx.csv
$ python main.py import_file --fp xxx.csv --folder ./my_folder
IMPORT file from: ./my_folder/xxx.csv
2. 組合命令
當(dāng)功能越來越多時,可能就會需要組合一些功能一起運(yùn)行,省得輸入一個一個的子命令。
class FileHandler(): def __init__(self, folder="./defalut_dir"): self.folder = folder def import_file(self, fp): print("IMPORT file from: {}".format(os.path.join(self.folder, fp))) def export_file(self, fp): print("EXPORT file to: {}".format(os.path.join(self.folder, fp))) class DatabaseHandler(): def __init__(self, src="aliyun-mysql", dst="tecent-mysql"): self.src = src self.dst = dst def import_db(self): print("IMPORT data from: {} to: {}".format(self.src, self.dst)) def export_db(self): print("EXPORT data from: {} to: {}".format(self.src, self.dst)) # 組合 FileHandler 和 DatabaseHandler class ComposeHandler(): def __init__(self): self.fh = FileHandler() self.dh = DatabaseHandler() def import_all(self, fp): self.fh.import_file(fp) self.dh.import_db() def export_all(self, fp): self.fh.export_file(fp) self.dh.export_db() if __name__ == "__main__": fire.Fire(ComposeHandler)
導(dǎo)出組合命令之后,不僅可以執(zhí)行組合命令,也可以只執(zhí)行子命令。
$ python main.py import_all --fp xxx.csv
IMPORT file from: ./defalut_dir/xxx.csv
IMPORT data from: aliyun-mysql to: tecent-mysql
$ python main.py export_all --fp xxx.csv
EXPORT file to: ./defalut_dir/xxx.csv
EXPORT data from: aliyun-mysql to: tecent-mysql
$ python main.py fh export_file --fp xxx.csv
EXPORT file to: ./defalut_dir/xxx.csv
$ python main.py dh export_db
EXPORT data from: aliyun-mysql to: tecent-mysql
3. 鏈?zhǔn)矫?/h2>
鏈?zhǔn)矫詈徒M合命令不一樣的地方在于:
組合命令中,每個命令之間一般是相互獨(dú)立的,
而鏈?zhǔn)矫钪?,上一個命令的執(zhí)行結(jié)果會對下一個命令造成影響。
比如:
class Stat(): def __init__(self): self.total = 0 self.avg = 0 self.n = 0 # 模擬統(tǒng)計合計值 def sum(self, n): self.n += n for i in range(n): self.total += i return self # 模擬求平均值 def average(self): if self.n == 0: self.avg = 0 else: self.avg = self.total / self.n return self # 顯示分析結(jié)果 def show(self): print("SUM: {}, and AVERAGE: {}".format(self.total, self.avg)) if __name__ == "__main__": fire.Fire(Stat)
執(zhí)行鏈?zhǔn)矫顣r,可以先求和,再求平均值,最后顯示結(jié)果:
$ python main.py sum 10 average show
SUM: 45, and AVERAGE: 4.5
因?yàn)槭擎準(zhǔn)矫?,所以可以多次?zhí)行:
$ python main.py sum 10 sum 10 average show
SUM: 90, and AVERAGE: 4.5
$ python main.py sum 10 sum 20 sum 30 average show
SUM: 670, and AVERAGE: 11.166666666666666
4. 復(fù)雜命令參數(shù)
上面的示例中,參數(shù)都是簡單的數(shù)據(jù)類型,比如字符串,數(shù)字之類的。
最后,介紹下復(fù)雜的命令參數(shù)如何使用,所謂復(fù)雜的參數(shù),就是元組,列表,字典等等。
def hello(data): tp = type(data).__name__ if tp == "tuple" or tp == "list": for item in data: print("hello: {}".format(item)) if tp == "dict": for k, v in data.items(): print("hello: key {}, val {}".format(k, v)) if __name__ == "__main__": fire.Fire(hello)
python
是弱類型語言,函數(shù)的參數(shù)可以是任何類型。
主要看看命令行中如何傳入復(fù)雜的類型:
$ python main.py "(aa, bb, cc)"
hello: aa
hello: bb
hello: cc
$ python main.py "[aa, bb, cc]"
hello: aa
hello: bb
hello: cc
$ python main.py "{aa: 11, bb: 22}"
hello: key aa, val 11
hello: key bb, val 22
5. 總結(jié)
Python
的Fire
庫是一個構(gòu)思非常巧妙的命令行接口庫,各種語言的命令行接口我接觸過不少,還沒有在其他編程語言中看到過類似的庫。
Fire
庫最方便的地方在于,你不用再關(guān)心命令行的參數(shù)(參數(shù)的解析一直是命令行程序中最讓人頭疼的地方),只要專注于自己要實(shí)現(xiàn)的功能。
此外,如果你已經(jīng)有一些python腳本的話,通過這個庫把它們改造成命令行程序也非常簡單。
到此這篇關(guān)于Python Fire實(shí)現(xiàn)自動生成命令行接口的文章就介紹到這了,更多相關(guān)Python Fire生成命令行接口內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解Python的循環(huán)結(jié)構(gòu)知識點(diǎn)
在本篇文章里小編給大家分享了關(guān)于Python循環(huán)結(jié)構(gòu)的相關(guān)知識點(diǎn)總結(jié)內(nèi)容,需要的朋友們跟著學(xué)習(xí)下吧。2019-05-05python深度學(xué)習(xí)之多標(biāo)簽分類器及pytorch實(shí)現(xiàn)源碼
這篇文章主要為大家介紹了python深度學(xué)習(xí)之多標(biāo)簽分類器的使用說明及pytorch的實(shí)現(xiàn)源碼,有需要的朋友可以借鑒參考下,希望能夠有所幫助2022-01-01python操作csv格式文件之csv.DictReader()方法
這篇文章主要介紹了python操作csv格式文件之csv.DictReader()方法,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,感興趣的小伙伴可以參考一下2022-06-06Python+OpenCV圖像處理——實(shí)現(xiàn)直線檢測
這篇文章主要介紹了Python+OpenCV如何實(shí)現(xiàn)直線檢測,幫助大家更好的利用python處理圖片,感興趣的朋友可以了解下2020-10-10Python編程使用DRF實(shí)現(xiàn)一次性驗(yàn)證碼OTP
今天講一下如何用 Django REST framework[1](DRF) 來實(shí)現(xiàn) OTP,閱讀本文需要一定的 DRF 的基礎(chǔ)知識,有需要的朋友可以借鑒參考下2021-09-09