首頁 > 軟體

Python的命令列引數範例詳解

2022-02-25 19:01:43

0. 命令列引數

通常,對於大型專案程式而言,執行程式的一個必要的步驟是正確處理命令列引數,這些命令列引數是提供給包含某種引數化資訊的程式或指令碼的引數。例如,在計算機視覺專案中,影象和不同型別的檔案通常作為命令列引數傳遞給指令碼,用於使程式可以處理不同圖片或者不同型別檔案。

命令列引數是引數化程式執行的一種常見且簡單的方法,下面主要介紹三種常見的獲取和解析命令列引數的方法。

1. sys.argv

為了處理命令列引數,Python 中內建了 sys.argv 模組,通過模組中的 sys.argv 就可以存取到所有的命令列引數,它的返回值是包含所有命令列引數的列表 (list)。當程式執行時,Python 從命令列獲取所有值並將它們儲存在 sys.argv 列表中。列表的第一個元素 sys.argv[0] 是指令碼的完整路徑(或指令碼名稱——取決於具體作業系統)。列表的第二個元素是指令碼的第一個命令列引數,即 sys.argv[1],依此類推。這可以通過下圖中清晰的看出,其中 script_1.py 指令碼使用兩個引數執行:

接下來,讓我們看看 sys.argv 是如何工作的,首先編寫 scripy_1.py 指令碼:

import sys
print("正在執行的指令碼名稱: '{}'".format(sys.argv[0]))
print("指令碼的引數數量: '{}'".format(len(sys.argv)))
print("指令碼的引數: '{}'".format(str(sys.argv)))

如果我們不使用任何引數執行這個指令碼:

python script_1.py

將會看到如下資訊:

正在執行的指令碼名稱: 'script_1.py'
指令碼的引數數量: '1'
指令碼的引數: '['script_1.py']'

如果我們使用多個引數執行此指令碼:

python script_1.py OpenCV -i test.png

將得到以下資訊:

正在執行的指令碼名稱: 'script_1.py'
指令碼的引數數量: '4'
指令碼的引數: '['script_1.py', 'OpenCV', '-i', 'test.png']'

如上所示,列表的第一個元素 script_1.py (sys.argv[0]) 是指令碼名稱。列表的第二個元素 (sys.argv[1]) OpenCV 是指令碼的第一個引數。但同時也可以看到,sys.argv 將命令列選項 -i 也識別為引數,這樣並不能方便的滿足我們的需求,因此引入 getopt 模組來識別命令列選項。

2. getopt

getopt 模組是專門處理命令列引數的模組,用於獲取命令列選項和引數。命令列選項使得程式的引數更加靈活,其支援短選項模式(-)和長選項模式(–)。
該模組提供了兩個方法及一個例外處理來解析命令列引數。

2.1 getopt.getopt 方法

getopt.getopt 方法用於解析命令列參數列,其語法格式如下:

getopt.getopt(args, options[, long_options])

方法引數說明如下表所示:

引數說明
args要解析的命令列參數列,一般是sys.argv[1:],需要過濾掉指令碼名(sys.argv[0])
options以字串的格式定義,options 後的冒號 “:” 表示如果設定該選項,必須有附加的引數,否則就不附加引數
long_options以列表的格式定義,long_options 後的等號 “=” 表示該選項必須有附加的引數,不帶冒號表示該選項不附加引數

該方法返回值由兩個元素組成: 第一個是 (option, value) 元組的列表。 第二個是參數列,包含那些沒有 - 或 – 的引數。
下面編寫 script_2.py 指令碼進行演示:

import sys
import getopt

def main(argv):
    input_file = ""
    output_file = ""
    # "hi:o:": 短格式分析串, h 後面沒有冒號, 表示後面不帶引數; i 和 o 後面帶有冒號, 表示後面帶引數
    # ["help", "input_file=", "output_file="]: 長格式分析串列表, help後面沒有等號, 表示後面不帶引數; input_file和output_file後面帶冒號, 表示後面帶引數
    # 返回值包括 `opts` 和 `args`, opts 是以元組為元素的列表, 每個元組的形式為: (選項, 附加引數),如: ('-i', 'test.png');
    # args是個列表,其中的元素是那些不含'-'或'--'的引數
    opts, args = getopt.getopt(argv[1:], "hi:o:", ["help", "input_file=", "output_file="])

    for opt, arg in opts:
        if opt in ("-h", "--help"):
            print('script_2.py -i <input_file> -o <output_file>')
            print('or: test_arg.py --input_file=<input_file> --output_file=<output_file>')
            sys.exit()
        elif opt in ("-i", "--input_file"):
            input_file = arg
        elif opt in ("-o", "--output_file"):
            output_file = arg
    print('輸入檔案為:', input_file)
    print('輸出檔案為:', output_file)

    # 列印不含'-'或'--'的引數
    for i in range(0, len(args)):
        print('不含'-'或'--'的引數 %s 為:%s' % (i + 1, args[i]))
        
if __name__ == "__main__":
    main(sys.argv)

使用帶有命令列選項的命令執行此指令碼,以下兩種方式是等價的:

# 方式1
python scripy_1.py -i test.png -o output.png OpenCV
# 方式2
python scripy_1.py --input_file test.png --output_file output.png OpenCV

輸出得到以下資訊:

輸入檔案為: test.png
輸出檔案為: output.png
不含'-'或'--'的引數 1 為:OpenCV

2.2 Exception getopt.GetoptError

在參數列中沒有找到所傳遞引數,或選項的需要的引數為空時會觸發該異常。異常的引數是一個字串,表示錯誤的原因。屬性 msg 和 opt 為相關選項的錯誤資訊。
在上述程式碼中新增例外處理,檢查此錯誤資訊:

# ...
def main(argv):
    input_file = ""
    output_file = ""
    try:
        opts, args = getopt.getopt(argv[1:], "hi:o", ["help", "input_file=", "output_file="])
    except getopt.GetoptError as e:
        print(e.msg)
        print(e.opt)
        sys.exit(2)
# ...

使用錯誤的格式選項傳遞引數執行指令碼:

python scripy_1.py -f

輸出以下錯誤資訊:

option -f not recognized
f

3. argparse

當程式中使用採用複雜引數或多個檔名時,推薦使用 Python 的 argparse 庫,它以系統的方式處理命令列引數,從而可以編寫使用者友好的命令列程式。Python 標準庫 argparse 同樣也是用於解析命令列引數的模組。首先,由程式確定所需的引數,然後, argparse 將這些引數解析為 sys.argv。此外,argparse 會生成幫助和使用資訊提示,並在提供無效引數時發出錯誤。

為了介紹此模組,編寫 script_3.py,如下所示:

import argparse
parser = argparse.ArgumentParser()
parser.parse_args()

不帶引數執行此指令碼不會向 stdout 顯示任何內容。但是,如果使用 --help 或 -h 選項,將得到指令碼的使用資訊提示:

usage: scripy_3.py [-h]
optional arguments:
-h, --help show this help message and exit

指定其他引數會導致錯誤,例如使用如下命令:

scripy_3.py -i

則會報導致錯誤:

usage: scripy_3.py [-h]
argparse_minimal.py: error: unrecognized arguments: -i

由於未定義引數,因此不允許其他引數,接下來就新增一個引數,編寫 script_4.py 指令碼:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("first_argument", help="this is the string text in connection with first_argument")
args = parser.parse_args()
print(args.first_argument)

這裡新增了 add_argument() 方法。此方法用於指定程式將接受哪些命令列選項,此處新增了 first_argument 引數。此外, argparse 模組儲存所有引數,將其名稱與每個新增引數的名稱相匹配——在此處為 first_argument 。為了獲得引數值,需要使用 args.first_argument。

如果此指令碼以下示方法執行,則輸出為 10:

python scripy_4.py 10

但如果指令碼在沒有引數的情況下執行,則將輸出以下資訊:

usage: scripy_4.py [-h] first_argument
scripy_4.py: error: the following arguments are required: first_argument

最後,如果我們使用 -h 選項執行指令碼,輸出將如下所示:

usage: scripy_4.py [-h] first_argument

positional arguments:
  first_argument  this is the string text in connection with first_argument

optional arguments:
  -h, --help      show this help message and exit

預設情況下,argparse 將提供的選項視為字串。因此,如果引數不是字串,則應使用 type 選項。使用 script_5.py 指令碼,其中新增了兩個引數,這兩個引數是 int 型別:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("first_number", help="first number to be added", type=int)
parser.add_argument("second_number", help="second number to be added", type=int)
args = parser.parse_args()
print("args: '{}'".format(args))
print("the sum is: '{}'".format(args.first_number + args.second_number))
args_dict = vars(parser.parse_args())
print("args_dict dictionary: '{}'".format(args_dict))
print("first argument from the dictionary: '{}'".format(args_dict["first_number"]))

在前面的範例中,通過呼叫 vars() 函數將引數儲存在字典中:

args_dict = vars(parser.parse_args())
print("args_dict dictionary: '{}'".format(args_dict))
print("first argument from the dictionary: '{}'".format(args_dict["first_number"]))

如果不帶引數執行指令碼:

python script_5.py

則輸出如下:

usage: scripy_5.py [-h] first_number second_number
scripy_5.py: error: the following arguments are required: first_number, second_number

此外,如果我們使用 -h 選項執行指令碼:

python script_5.py --help

輸出將如下所示:

usage: scripy_1.py [-h] first_number second_number

positional arguments:
  first_number   first number to be added
  second_number  second number to be added

optional arguments:
  -h, --help     show this help message and exit

如果此指令碼以如下方式執行:

python script_5.py 123 456

則輸出如下:

args: 'Namespace(first_number=123, second_number=456)'
the sum is: '579'
args_dict dictionary: '{'first_number': 123, 'second_number': 456}'
first argument from the dictionary: '123'

更多 argparse 的高階介紹可以在官方檔案中看到,其中包括了大量範例

總結

到此這篇關於Python命令列引數詳解的文章就介紹到這了,更多相關Python命令列引數內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com