1. 程式人生 > >【Python】自動生成命令列工具

【Python】自動生成命令列工具

Python 中用於生成命令列介面(Command Line Interfaces, CLIs)的工具已經有一些了,例如已經成為 Python 標準庫的 argparse 和第三方的 click ,這些都是很不錯的工具。但是這些工具為 Python 程式生成 CLIs 的時候稍顯麻煩,需要增加的地方比較多,過程稍顯繁瑣。今天介紹的這個工具,幾乎可以不改變原始程式碼就可以生成 CLIs,是 Google 於 今年(2017 年)3 月 2 日宣佈在 GitHub 上開源的。

fire 開源

文中的三個程式檔案可以在 這裡 打包下載。

更新

這裡我會列出對本文的更新。

  • 2017 年 10 月 18 日:優化排版,與其他博文保持風格統一。

簡介

大致的簡介我在上面簡單說了下,下面我引用下官方簡介:

Python Fire is a library for creating command line interfaces (CLIs) from absolutely any Python object.

  • Python Fire is a simple way to create a CLI in Python.
  • Python Fire is a helpful tool for developing and debugging Python code.
  • Python Fire helps with exploring existing code or turning other people’s code into a CLI.
  • Python Fire makes transitioning between Bash and Python easier.
  • Python Fire makes using a Python REPL easier by setting up the REPL with the modules and variables you’ll need already imported and created.

可以看出來,Fire 不僅僅是一個生成 CLIs 的工具,而且還可以除錯 Python 程式,互動式的使用 Fire 。

安裝

在命令列中執行 pip install fire

即可安裝。

用法

使用 fire 生成 CLIs 的基本用法就是使用 fire.Fire(),可以傳入任意引數,用官方的說法就是 any Python object 。下面我舉三個例子簡單的說明一下用法,更多的用法大家可以參考 The Python Fire GuideUsing a Fire CLI

下面的例子均是以計算時間差(兩個日期之間相差的天數)的程式為例。

單個函式

檔案 test-fire.py

import fire
import datetime

def cal_days(date_str1, date_str2):
    '''計算兩個日期之間的天數'''

    date_str1 = str(date_str1)
    date_str2 = str(date_str2)
    d1 = datetime.datetime.strptime(date_str1, '%Y%m%d')
    d2 = datetime.datetime.strptime(date_str2, '%Y%m%d')
    delta = d1 - d2
    return delta.days


if __name__ == '__main__':
    fire.Fire(cal_days)

這個程式中只有一個函式 cal_days,最後使用 fire.Fire(cal_days) 來生成 CLIs。

我們可以先用下面的語句檢視幫助資訊:

$ python test-fire.py
Fire trace:
1. Initial component
2. ('The function received no value for the required argument:', 'date_str1')

Type:        function
String form: <function cal_days at 0x000002F0099B7F28>
File:        d:\masterfiles\notebook\test-fire.py
Line:        4
Docstring:   計算兩個日期之間的天數

Usage:       test-fire.py DATE_STR1 DATE_STR2
             test-fire.py --date-str1 DATE_STR1 --date-str2 DATE_STR2

我們可以看到傳給 fire.Fire() 的引數型別(function)、檔案路徑、文件字串、引數用法等資訊。

現在我們試著計算一下 2017 年 4 月 21 號和 2017 年 4 月 1 號差了多少天:

$ python test-fire.py 20170421 20170401
20

當然,你也可以使用 python test-fire.py --date-str1 20170421 --date-str2 20170401

此外,對於這種單個函式的情況,程式的最後一行 fire.Fire(cal_days) 可以改為 fire.Fire(),結果完全一樣,fire.Fire() 會預設使用 cal_days() 函式。

多個函式

檔案 test-fire-2func.py

import fire
import datetime

def cal_days(date_str1, date_str2):
    '''計算兩個日期之間的天數'''

    date_str1 = str(date_str1)
    date_str2 = str(date_str2)
    d1 = datetime.datetime.strptime(date_str1, '%Y%m%d')
    d2 = datetime.datetime.strptime(date_str2, '%Y%m%d')
    delta = d1 - d2
    return delta.days


def days2today(date_str):
    '''計算某天距離今天的天數'''

    date_str = str(date_str)
    d = datetime.datetime.strptime(date_str, '%Y%m%d')
    delta = datetime.datetime.now() - d
    return delta.days


if __name__ == '__main__':
    fire.Fire()

這個程式比 test-fire.py 多了一個函式,但是結尾處仍然使用 fire.Fire() 來生成 CLIs。我們先不輸任何引數:

$ python test-fire-2func.py 20170401
Fire trace:
1. Initial component
2. ('Cannot find target in dict', '20170401', {'__name__': '__main__', 'datetime': <module 'datetime' from 'C:\\Users\\secsi\\Anaconda3\\lib\\datetime.py'>, 'cal_days': <function cal_days at 0x0000027A855E7F28>, 'days2today': <function days2today at 0x0000027A86EC6B70>, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000027A85655A90>, '__file__': 'test-fire-2func.py', '__cached__': None, 'fire': <module 'fire' from 'C:\\Users\\secsi\\Anaconda3\\lib\\site-packages\\fire\\__init__.py'>, '__package__': None, '__builtins__': <module 'builtins' (built-in)>, '__doc__': None, '__spec__': None})

Type:        dict
String form: {'__name__': '__main__', 'datetime': <module 'datetime' from 'C:\\Users\\secsi\\Anaconda3\\lib\\d <...> kage__': None, '__builtins__': <module 'builtins' (built-in)>, '__doc__': None, '__spec__': None}
Length:      12

Usage:       test-fire-2func.py
             test-fire-2func.py datetime
             test-fire-2func.py cal-days
             test-fire-2func.py days2today
             test-fire-2func.py fire

程式中有個兩個函式,而我們執行 python test-fire-2func.py 20170401 的時候卻沒有指定使用哪個函式,所以會報錯。

正確的寫法應該是這樣的:

$ python test-fire-2func.py days2today 20170401
21
$ python test-fire-2func.py cal_days 20170422 20170401
21

也就是說在後面跟上要使用的函式名。

物件(類)

Fire 既然能夠 fire 任何 Python 物件,那麼給 fire.Fire() 傳一個類也是完全可以的。下面是一個例子:

檔案 test-fire-class.py

import fire
import datetime


class DateStr(object):

    def cal_days(self, date_str1, date_str2):
        '''計算兩個日期之間的天數'''
        date_str1 = str(date_str1)
        date_str2 = str(date_str2)
        d1 = datetime.datetime.strptime(date_str1, '%Y%m%d')
        d2 = datetime.datetime.strptime(date_str2, '%Y%m%d')
        delta = d1 - d2
        return delta.days

    def days2today(self, date_str):
        '''計算某天距離今天的天數'''
        date_str = str(date_str)
        d = datetime.datetime.strptime(date_str, '%Y%m%d')
        delta = datetime.datetime.now() - d
        return delta.days


if __name__ == '__main__':
    fire.Fire(DateStr)

這裡我定義了一個 DateStr 類,有兩個類方法 cal_daysdays2today ,那麼我只需 fire.Fire(DateStr) 就可以呼叫這兩個類方法。

$  python test-fire-class.py days2today 20170401
21
$ python test-fire-class.py cal-days 20170422 20170401
21

還有幾點

  • fire 預設使用 - 作為引數分隔符,所以如果你要在命令列傳入類似 2017-04-22 的引數時,那麼程式接收到的引數就肯定不是 2017-04-22 了,你需要使用 --separator 來改變分隔符,參考 Changing the Separator
  • fire 會自動區分你在命令列傳入的引數的型別,例如 20170422 會自動識別成 inthello 會自動識別成 str'(1,2)' 會自動識別成 tuple'{"name": "Alan Lee"}' 會自動識別成 dict。但是你如果想要傳入一個字串型別的 20170422 怎麼辦?那就需要這樣寫:'"20170422"' 或者 "'20170422'" 或者 \"20170422\",總之呢,就是加一個轉義,因為命令列預設會吃掉你的引號。參考 Argument Parsing

END

相關推薦

Python自動生成命令工具

Python 中用於生成命令列介面(Command Line Interfaces, CLIs)的工具已經有一些了,例如已經成為 Python 標準庫的 argparse 和第三方的 click ,這些都是很不錯的工具。但是這些工具為 Python 程式生成 C

Python 文件目錄比較工具filecmp和difflib

返回 我沒 直接 既然 hash this 上下 direct 不同   在一些運維場景中,常常需要比較兩個環境中的應用目錄結構(是否有文件/目錄層面上的增刪)以及比較兩個環境中同名文件內容的不同(即文件層面上的改)。Python自帶了兩個內建模塊可以很好地完成這個工作,f

Pythonuuid生成唯一ID

uuid是128位的全域性唯一識別符號(univeral unique identifier),通常用一個32位的字串的形式來表現。有時也稱guid(global unique identifier)。python中自帶了uuid模組來進行uuid的生成和管理工作。(pyth

自動生成整型序列

目錄:https://www.cnblogs.com/liqingwen/p/10261436.html 當需要一系列整型值時,可以使用某種迴圈手動建立,或者可以使用 Enumerable.Range 方法。以下為程式碼說明: var oneT

Python如何生成柯西分佈隨機數

Python中生成標準柯西分佈的函式是:numpy.random.standard_cauchy(size),我就在想,能否生成一個非標準的柯西隨機數呢?那麼面臨幾個問題:(1)標準柯西隨機數和非標準可惜隨機數之間有沒有之間轉化關係?(沒有)(2)柯西隨機數是怎麼生成的?(3

PEWindows平臺命令中使用vcvarsall.bat配置編譯環境

###Date: 2017/9/20 一、關於命令列編譯環境的配置方法 對於VS2015,%VS140COMNTOOLS%/VC下就有vcvarsall.bat,用於生成命令列編譯環境。 對於V

Hibernate自動生成資料庫表

  雖說整體上對SSH有一定的把控使用能力,但還是見微知著,點滴積累。Hibernate本意是冬眠,很好的封裝了JDBC和資料庫互動,實現了物件的持久化操作。所以也可以理解物件的持久化其實就是“冬眠”

JavaJava的命令引數

說明 命令列引數就是main方法裡面的引數String[] args,args只是資料型別的一個名稱,可任意命名 當你在Java命令列後面帶上引數,JVM就直接把引數存放到了main方法中的引數String數組裡 格式 Java中的命令列引數格式: public stat

生成命令介面--google開源的fire使用體驗python-fire

在python中,命令列介面常用的argparse 和click,但是相對於python-fire 來說靈活度太缺了,fire可以直接將python中的函式,以命令列顯示. 簡單的介紹幾個例子: #!/usr/bin/env python # -*- coding: utf-8

Pythonpytest常用命令選項

https://www.cnblogs.com/cnkemi/p/9989019.html http://www.cnblogs.com/cnkemi/p/10002788.html pytest 常用命令列選項(一)   pytest有豐富的命令列選項,以滿足不同的需要,下面對常用的命令列選項作下簡單介

MacMac OS X 安裝GNU命令工具

macos的很多使用者都是做it相關的人,類unix系統帶來了很多方面,尤其是經常和linux打交道的人。 但是作為經常使用linux 命令列的人發現macos中的命令列工具很多都是bsd工具,跟linux下得使用方式開始差距挺大的,那麼怎麼安裝GNU命令

輕鬆學習Ionic (四) 修改應用圖示及新增啟動畫面(更新官方命令工具自動生成

 <platform name="android">              <icon src="res/android/ldpi.png" density="ldpi" />              <icon src="res/android/mdpi.png" de

FFMpeg視訊開發與應用基礎一、使用FFmpeg命令工具和批處理指令碼進行簡單的音視訊檔案編輯

《FFMpeg視訊開發與應用基礎——使用FFMpeg工具與SDK》視訊教程已經在“CSDN學院”上線,視訊中包含了從0開始逐行程式碼實現FFMpeg視訊開發的過程,歡迎觀看!連結地址:FFMpeg視訊開發與應用基礎——使用FFMpeg工具與SDK

全網最詳細的一個超級好用的命令工具Cmder的優點有哪些?

    不多說,直接上乾貨!   1、把conemu,msysgit和clink打包在一起,讓你無需配置就能使用一個真正乾淨的Linux終端!甚至還附帶了漂亮的monokai配色主題。   2、選中右擊直接可以實現複製功能   3、主控臺文字自動放大縮小功能,按下Ctrl+滑鼠滾輪就可以

全網最詳細的一個超級好用的命令工具Cmder的下載與安裝(圖文詳解)

    不多說,直接上乾貨!         下載的時候,有兩個版本,分別是mini與full版;唯一的差別在於有沒有內建msysgit工具,這是Git for Windows的標準配備;全安裝版 cmder 自帶了 msysgit, 壓縮包 23M, 除了 git 本身這個命令之外, 裡面

全網最詳細的一個超級好用的命令工具Cmder的安裝之後的一些配置(圖文詳解)

    不多說,直接上乾貨! 1、修改命令提示符λ為$    首先,我們看到    進入解壓後的cmder的目錄,進入vendor,開啟init.bat檔案。   修改第15行的程式碼 @prompt $E[1;32;40m$P$S

全網最詳細的一個超級好用的命令工具Cmder是什麼?

    不多說,直接上乾貨! Cmder是什麼?     一款Windows環境下非常簡潔美觀易用的cmd替代者,它支援了大部分的Linux命令。支援ssh連線linux,使用起來非常方便。比起cmd、powershell、conEmu,其介面美觀簡潔,功能強大。        

ffmpeg視訊編解碼之ffmpeg命令工具的常用命令彙總

H264視訊轉ts視訊流 ffmpeg -i test.h264 -vcodec copy -f mpegts test.ts H264視訊轉mp4 ffmpeg -i test.h264 -vcodec copy -f mp4 test.mp4 ts視訊轉mp4 ffmpeg

Wireshark命令工具tshark使用小記

1、目的   寫這篇部落格的目的主要是為了方便查閱,使用wireshark可以分析資料包,可以通過編輯過濾表示式來達到對資料的分析;但我的需求是,怎麼樣把Data部分匯出來,因為後續的工作主要針對資料包的Data部分,主要是對本地儲存的.pcap檔案進行解析。這

工具輕量級 linux 命令發郵件工具--SendEmail

An Email Program for Sending SMTP Mail from a Command Line About SendEmail SendEmail is a lightweight, command line SMTP email clien