国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Python > 正文

使用Python編寫類UNIX系統的命令行工具的教程

2019-11-25 17:44:01
字體:
來源:轉載
供稿:網友

引言

您是否能編寫命令行工具?也許您可以,但您能編寫出真正好用的命令行工具嗎?本文討論使用 Python 來創建一個強健的命令行工具,并帶有內置的幫助菜單、錯誤處理和選項處理。由于一些奇怪的原因,很多人并不了解 Python? 的標準庫具有制作功能極其強大的 *NIX 命令行工具所需的全部工具。

可以這樣說,Python 是制作 *NIX 命令行工具的最佳語言,因為它依照“batteries-included”的哲學方式工作,并且強調提供可讀性高的代碼。但僅作為提醒,當您發現使用 Python 創建命令行工具是一件多么簡單的事情時,這些想法很危險,您的生活可能被攪得一團糟。據我所知,至今還沒有發表過詳細說明使用 Python 創建命令行工具的文章,因此我希望您喜歡這篇文章。
設置

Python 標準庫中的 optparse 模塊可完成創建命令行工具的大部分瑣碎工作。optparse 包含在 Python 2.3 中,因此該模塊將包括在許多 *NIX 操作系統中。如果由于某種原因,您使用的操作系統不包含所需要的模塊,那么值得慶幸的是,Python 的最新版本已經過測試并編譯到幾乎任何 *NIX 操作系統中。Python 支持的系統包括 IBM? AIX?、HP-UX、Solaris、Free BSD、Red Hat Linux?、Ubuntu、OS X、IRIX,甚至包括幾種 Nokia 手機。
創建 Hello World 命令行工具

編寫優秀的命令行工具的第一步是定義要解決的問題。這對您工具的成功至關重要。這對于以盡可能簡單的方法解決問題也同樣重要。這里明確地采用了 KISS(Keep It Simple Stupid,保持簡單)準則。只有在實現并測試了計劃內功能之后才添加選項和增加其他功能。

我們首先從創建 Hello World 命令行工具開始。按照上面的建議,我們使用盡可能簡單的術語來定義問題。

問題定義:我希望創建一個命令行工具,默認打印 Hello World,并提供用于打印不通人的姓名的選項。

基于上述說明,可以提供一個包含少量代碼的解決方案。
Hello World 命令行接口 (CLI)

        

 #!/usr/bin/env python     import optparse          def main():      p = optparse.OptionParser()      p.add_option('--person', '-p', default="world")      options, arguments = p.parse_args()      print 'Hello %s' % options.person          if __name__ == '__main__':      main()

如果運行此代碼,預期的輸出如下:

Hello world

但是,我們通過少量代碼所能做到的遠不止于此。我們可以獲得自動生成的幫助菜單:

python hello_cli.py --help       Usage: hello_cli.py [options]          Options:     -h, --help      show this help message and exit     -p PERSON, --person=PERSON

從幫助菜單中可以了解到,我們可以使用兩種方法來更改 Hello World 的輸出:

python hello_cli.py -p guidoHello guido

我們還實現了自動生成的錯誤處理:

python hello_cli.py --name matzUsage: hello_cli.py [options]     hello_cli.py: error: no such option: --name

如果您還沒有使用過 Python 的 optparse 模塊,那么您剛才可能會大吃一驚,并思忖使用 Python 可以編寫的所有這些不可思議的工具。如果您剛開始接觸 Python,那么您可能會驚訝于 Python 讓一切變得如此簡單。“XKCD”網站發表了關于“Python 是如此簡單”主題的非常有趣的漫畫,已包括在參考資料中。
創建有用的命令行工具

既然我們已經打好了基礎,我們就可以繼續創建解決特定問題的工具。對于本例,我們將使用 Python 的名為 Scapy 的網絡庫和交互式工具。Scapy 可以在大多數 *NIX 系統上正常工作,可以在第 2 層和第 3 層上發送數據包,并允許您創建只有幾行 Python 代碼的非常復雜的工具。如果您希望按部就班從頭開始,請確保您正確地安裝了必要的軟件。

我們先定義要解決的新問題。

問題:我希望創建一個使用 IP 地址或子網作為參數的命令行工具,并向標準輸出返回 MAC 地址或 MAC 地址列表以及它們各自的 IP 地址。

既然我們已經清楚地定義了問題,讓我嘗試將問題分解為盡可能簡單的部分,然后逐一解決這些部分。對于這一問題,我看到了兩個獨立的部分。第一部分是編寫接收 IP 地址或子網范圍的函數,并返回 MAC 地址或 MAC 地址列表。我們可以在解決此問題之后再考慮將其集成到命令行工具中。
解決方案第 1 部分:創建通過 IP 地址確定 MAC 地址的 Python 函數

arpingfrom scapy import srp,Ether,ARP,confconf.verb=0ans,unans=srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst="10.0.1.1"),timeout=2)for snd, rcv in ans:print rcv.sprintf(r"%Ether.src% %ARP.psrc%")

該命令的輸出是:

    sudo python arping.py    00:00:00:00:00:01 10.0.1.1

請注意,使用 scapy 執行操作要求提升的權限,因此我們必須使用 sudo。考慮到本文的目的,我還將實際輸出更改為包括偽 MAC 地址。我們已經證實了我們可以通過 IP 地址找到 MAC 地址。我們需要整理此代碼以接受 IP 地址或子網并返回 MAC 地址和 IP 地址對。
arping 函數

    #!/usr/bin/env python        from scapy import srp,Ether,ARP,conf        def arping(iprange="10.0.1.0/24"):     conf.verb=0     ans,unans=srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst=iprange),               timeout=2)         collection = []     for snd, rcv in ans:      result = rcv.sprintf(r"%ARP.psrc% %Ether.src%").split()      collection.append(result)     return collection        #Print results    values = arping()        for ip,mac in values:    print ip,mac

正如您看到的,我們編寫了一個函數,該函數接受 IP 地址或網絡并返回嵌套的 IP/MAC 地址列表。我們現已為第二部分做好準備,為我們的工具創建一個命令行接口。
解決方案第 2 部分:從我們的 arping 函數創建命令行工具

在本例中,我們綜合本文前面部分的想法,創建一個能解決我們初始問題的完整命令行工具。
arping CLI

  

 #!/usr/bin/env python    import optparse  from scapy import srp,Ether,ARP,conf    def arping(iprange="10.0.1.0/24"):   """Arping function takes IP Address or Network, returns nested mac/ip list"""     conf.verb=0   ans,unans=srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst=iprange),        timeout=2)     collection = []   for snd, rcv in ans:     result = rcv.sprintf(r"%ARP.psrc% %Ether.src%").split()     collection.append(result)   return collection    def main():   """Runs program and handles command line options"""     p = optparse.OptionParser(description=' Finds MAC Address of IP address(es)',                  prog='pyarping',                  version='pyarping 0.1',                  usage='%prog [10.0.1.1 or 10.0.1.0/24]')    options, arguments = p.parse_args()  if len(arguments) == 1:   values = arping(iprange=arguments)   for ip, mac in values:    print ip, mac  else:   p.print_help()    if __name__ == '__main__':   main()

對以上腳本進行幾點說明將有助于我們了解 optparse 的工作方式。

首先,必須創建 optparse.OptionParser() 的一個實例,并且接受如下所示的可選參數:

 

復制代碼 代碼如下:
description, prog, version, and usage

這些參數的含義基本上可以不言自明,但我希望確認的一點是,您應該了解 optparse 雖然功能強大,但并不是無所不能。它具有明確定義的接口,可用于快速創建命令行工具。

其次,在如下行中:

復制代碼 代碼如下:
options, arguments = p.parse_args()

該行的作用是將選項和參數劃分為不同的位。在上述代碼中,我們預期恰有一個參數,因此我指定必須只有一個參數值,并將該值傳遞給 arping 函數。

    

   if len(arguments) == 1:      values = arping(iprange=arguments)

為了進一步說明,讓我們運行下面的命令以了解其工作方式:

     sudo python arping.py 10.0.1.1          10.0.1.1 00:00:00:00:00:01

在上述示例中,參數為 10.0.1.1,由于正如我在條件語句中指定的那樣只有一個參數,因此該參數被傳遞給 arping 函數。如果存在選項,它們將在 options, arguments = p.parse_args() 方法中傳遞給 options。讓我們看一下,當我們分解命令行工具的預期用例并賦予該用例兩個參數時將會發生什么情況:

     sudo python arping.py 10.0.1.1 10.0.1.3     Usage: pyarping [10.0.1.1 or 10.0.1.0/24]          Finds MAC Address or IP address(es)          Options:     --version  show program's version number and exit     -h, --help show this help message and exit

根據我為參數構建的條件語句的結構,如果參數的數目不為 1,它將自動打開幫助菜單:

     if len(arguments) == 1:      values = arping(iprange=arguments)      for ip, mac in values:       print ip, mac     else:      p.print_help()

這是一種用于控制工具的工作方式的重要方法,因為您可以使用參數的個數或特定選項的名稱作為控制命令行工具的流程的機制。因為我們在最初的 Hello World 示例中涉及了選項的創建,接下來通過略微更改主函數向我們的命令行工具添加幾個選項:
arping CLI main 函數

def main(): """Runs program and handles command line options""" p = optparse.OptionParser(description='Finds MAC Address of IP address(es)',              prog='pyarping',              version='pyarping 0.1',              usage='%prog [10.0.1.1 or 10.0.1.0/24]') p.add_option('-m', '--mac', action ='store_true', help='returns only mac address') p.add_option('-v', '--verbose', action ='store_true', help='returns verbose output') options, arguments = p.parse_args() if len(arguments) == 1:  values = arping(iprange=arguments)  if options.mac:   for ip, mac in values:    print mac  elif options.verbose:   for ip, mac in values:    print "IP: %s MAC: %s " % (ip, mac)  else:   for ip, mac in values:    print ip, mac else:  p.print_help()

所做的主要更改是創建了基于是否指定了某個選項的條件語句。請注意,與 Hello World 命令行工具不同,我們僅使用選項作為我們工具的 true/false 信號。對于

主站蜘蛛池模板: 湘阴县| 丰原市| 秦皇岛市| 武安市| 阜平县| 涿州市| 洪江市| 肇州县| 岳普湖县| 鄱阳县| 乐亭县| 突泉县| 阿拉善左旗| 马尔康县| 绥宁县| 安徽省| 吉林省| 磴口县| 堆龙德庆县| 华池县| 盐亭县| 太仓市| 晴隆县| 武安市| 凉城县| 新余市| 凌云县| 师宗县| 乐业县| 商丘市| 通山县| 武胜县| 温泉县| 望谟县| 肥东县| 石门县| 左贡县| 兴城市| 湘阴县| 崇仁县| 嘉祥县|