日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

用 Python 解析命令行參數 | Linux 中國

 

借鑒 C 語言的歷史,學習如何用 Python 編寫有用的 CLI 程序。

  • 來源:https://linux.cn/article-12286-1.html
  • 作者:Erik O'shaughnessy
  • 譯者:Xingyu.Wang

本文的目標很簡單:幫助新的 Python 開發者了解一些關于 命令行接口 (CLI)的歷史和術語,并探討如何在 Python 中編寫這些有用的程序。

最初……

首先,從 Unix 的角度談談命令行界面設計。

Unix 是一種計算機操作系統,也是 Linux 和 macOS(以及許多其他操作系統)的祖先。在圖形用戶界面之前,用戶通過命令行提示符與計算機進行交互(想想如今的 Bash 環境)。在 Unix 下開發這些程序的主要語言是 C ,它的 功能 非常強大。

因此,我們至少應該了解 C 程序 的基礎知識。

假設你沒有讀過上面那個鏈接的內容,C 程序的基本架構是一個叫做 main 的函數,它的簽名是這樣的。

   int main(int argc, char **argv)
   {
   ...
   }

對于 Python 程序員來說,這應該不會顯得太奇怪。C 函數首先有一個返回類型、一個函數名,然后是括號內的類型化參數。最后,函數的主體位于大括號之間。函數名 main 是 運行時鏈接器 (構造和運行程序的程序)如何決定從哪里開始執行你的程序。如果你寫了一個 C 程序,而它沒有包含一個名為 main 的函數,它將什么也做不了。傷心。

函數參數變量 argc 和 argv 共同描述了程序被調用時用戶在命令行輸入的字符串列表。在典型的 Unix 命名傳統中,argc 的意思是“ 參數計數(argument count)”,argv 的意思是“ 參數向量(argument vector)”。向量聽起來比列表更酷,而 argl 聽起來就像一個要勒死的求救聲。我們是 Unix 系統的程序員,我們不求救。我們讓其他人哭著求救。

再進一步

$ ./myprog foo bar -x baz

如果 myprog 是用 C 語言實現的,則 argc 的值是 5,而 argv 是一個有五個條目的字符指針數組。(不要擔心,如果這聽起來過于技術,那換句話說,這是一個由五個字符串組成的列表。)向量中的第一個條目 argv[0] 是程序的名稱。argv 的其余部分包含參數。

   argv[0] == "./myprog"
   argv[1] == "foo"
   argv[2] == "bar"
   argv[3] == "-x"
   argv[4] == "baz"
   
   /* 注:不是有效的 C 代碼 */

在 C 語言中,你有很多方法來處理 argv 中的字符串。你可以手動地循環處理數組 argv,并根據程序的需要解釋每個字符串。這相對來說比較簡單,但會導致程序的接口大相徑庭,因為不同的程序員對什么是“好”有不同的想法。

include <stdio.h>

/* 一個打印 argv 內容的簡單 C 程序。 */

int main(int argc, char **argv) {
    int i;
   
    for(i=0; i<argc; i++)
      printf("%sn", argv[i]);
}

早期對命令行標準化的嘗試

命令行武器庫中的下一個武器是一個叫做 getopt 的 C 標準庫 函數。這個函數允許程序員解析開關,即前面帶破折號的參數(比如 -x),并且可以選擇將后續參數與它們的開關配對。想想 /bin/ls -alSh 這樣的命令調用,getopt 就是最初用來解析該參數串的函數。使用 getopt 使命令行的解析變得相當簡單,并改善了用戶體驗(UX)。

include <stdio.h>
#include <getopt.h>

#define OPTSTR "b:f:"

extern char *optarg;

int main(int argc, char **argv) {
    int opt;
    char *bar = NULL;
    char *foo = NULL;
   
    while((opt=getopt(argc, argv, OPTSTR)) != EOF)
       switch(opt) {
          case 'b':
              bar = optarg;
              break;
          case 'f':
              foo = optarg;
              break;
          case 'h':
          default':
              fprintf(stderr, "Huh? try again.");
              exit(-1);
              /* NOTREACHED */
       }
    printf("%sn", foo ? foo : "Empty foo");
    printf("%sn", bar ? bar : "Empty bar");
}

就個人而言,我希望 Python 有開關,但這 永遠 、永遠不會 發生 。

GNU 時代

GNU 項目出現了,并為他們實現的傳統 Unix 命令行工具引入了更長的格式參數,比如--file-format foo。當然,我們這些 Unix 程序員很討厭這樣,因為打字太麻煩了,但是就像我們這些舊時代的恐龍一樣,我們輸了,因為用戶喜歡更長的選項。我從來沒有寫過任何使用 GNU 風格選項解析的代碼,所以這里沒有代碼示例。

GNU 風格的參數也接受像 -f foo 這樣的短名,也必須支持。所有這些選擇都給程序員帶來了更多的工作量,因為他們只想知道用戶要求的是什么,然后繼續進行下去。但用戶得到了更一致的用戶體驗:長格式選項、短格式選項和自動生成的幫助,使用戶不必再試圖閱讀臭名昭著的難以解析的 手冊 頁面(參見 ps 這個特別糟糕的例子)。

但我們正在討論 Python?

你現在已經接觸了足夠多(太多?)的命令行的歷史,對如何用我們最喜歡的語言來編寫 CLI 有了一些背景知識。Python 在命令行解析方面給出了類似的幾個選擇:自己解析, 自給自足(batteries-included)的方式,以及大量的第三方方式。你選擇哪一種取決于你的特定情況和需求。

首先,自己解析

你可以從 sys 模塊中獲取程序的參數。

import sys

if __name__ == '__main__':
   for value in sys.argv:
       print(value)

自給自足

在 Python 標準庫中已經有幾個參數解析模塊的實現: getopt 、 optparse ,以及最近的 argparse 。argparse 允許程序員為用戶提供一致的、有幫助的用戶體驗,但就像它的 GNU 前輩一樣,它需要程序員做大量的工作和“ 模板代碼 ”才能使它“奏效”。

from argparse import ArgumentParser

if __name__ == "__main__":

   argparser = ArgumentParser(description='My Cool Program')
   argparser.add_argument("--foo", "-f", help="A user supplied foo")
   argparser.add_argument("--bar", "-b", help="A user supplied bar")
   
   results = argparser.parse_args()
   print(results.foo, results.bar)

好處是當用戶調用 --help 時,有自動生成的幫助。但是 自給自足 (batteries included)的優勢呢?有時,你的項目情況決定了你對第三方庫的訪問是有限的,或者說是沒有,你不得不用 Python 標準庫來“湊合”。

CLI 的現代方法

然后是 Click 。Click 框架使用 裝飾器 的方式來構建命令行解析。突然間,寫一個豐富的命令行界面變得有趣而簡單。在裝飾器的酷炫和未來感的使用下,很多復雜的東西都消失了,用戶驚嘆于自動支持關鍵字補完以及上下文幫助。所有這些都比以前的解決方案寫的代碼更少。任何時候,只要你能寫更少的代碼,還能把事情做好,就是一種勝利。而我們都想要勝利。

import click

@click.command()
@click.option("-f", "--foo", default="foo", help="User supplied foo.")
@click.option("-b", "--bar", default="bar", help="User supplied bar.")
def echo(foo, bar):
    """My Cool Program
   
    It does stuff. Here is the documentation for it.
    """
    print(foo, bar)
   
if __name__ == "__main__":
    echo()

你可以在 @click.option 裝飾器中看到一些與 argparse 相同的模板代碼。但是創建和管理參數分析器的“工作”已經被抽象化了。現在,命令行參數被解析,而值被賦給函數參數,從而函數 echo 被魔法般地調用。

在 Click 接口中添加參數就像在堆棧中添加另一個裝飾符并將新的參數添加到函數定義中一樣簡單。

但是,等等,還有更多!

Typer 建立在 Click 之上,是一個更新的 CLI 框架,它結合了 Click 的功能和現代 Python 類型提示 。使用 Click 的缺點之一是必須在函數中添加一堆裝飾符。CLI 參數必須在兩個地方指定:裝飾符和函數參數列表。Typer 免去你造輪子 去寫 CLI 規范,讓代碼更容易閱讀和維護。

import typer

cli = typer.Typer()

@cli.command()
def echo(foo: str = "foo", bar: str = "bar"):
    """My Cool Program
   
    It does stuff. Here is the documentation for it.
    """
    print(foo, bar)
   
if __name__ == "__main__":
    cli()

是時候開始寫一些代碼了

哪種方法是正確的?這取決于你的用例。你是在寫一個只有你才會使用的快速而粗略的腳本嗎?直接使用 sys.argv 然后繼續編碼。你需要更強大的命令行解析嗎?也許 argparse 就夠了。你是否有很多子命令和復雜的選項,你的團隊是否會每天使用它?現在你一定要考慮一下 Click 或 Typer。作為一個程序員的樂趣之一就是魔改出替代實現,看看哪一個最適合你。

最后,在 Python 中有很多用于解析命令行參數的第三方軟件包。我只介紹了我喜歡或使用過的那些。你喜歡和/或使用不同的包是完全可以的,也是我們所期望的。我的建議是先從這些包開始,然后看看你最終的結果。

去寫一些很酷的東西吧。


via: https://opensource.com/article/20/6/c-python-cli

作者: Erik O'Shaughnessy 選題: lujun9972 譯者: wxy 校對: wxy

本文由 LCTT 原創編譯, Linux中國 榮譽推出

分享到:
標簽:命令行 參數 Python
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定