【💊 Python的解憂錦囊】ArgumentParser 布林與陣列的處理技巧(boolean/array)

2023/09/13閱讀時間約 6 分鐘

您是否苦於網路資訊爆炸嗎? 教學何其多,但卻無法好好選擇的困境呢? 歡迎加入「🔒 阿Han的軟體心法實戰營」, 這裡不給您冗餘的雜訊, 單刀直入直接送您重點, 避開選擇障礙的困境, 讓您獲得業界標準的開發起手式, 成為Top 1的頂尖人才。

我們是不是常常看到一些很厲害的專案, 只要「pip install xxx」之後就可以作為可執行檔的命令列形式進行運作? 這是不是很酷? 而Python內建的模組其實就能夠完成這部份的設計了! 我們接下來也會稍微簡介一番。

說到這裡,如果您也想要自己製作套件包,歡迎來「【🔒 Python 先修班】教你親手打包專屬套件庫的手作課」聊聊,讓我們一起手作一包套件包吧!

雖然主題是關於「Boolean」與「Array」輸入參數的處理方式, 但我們也是會藉著這個主題順便說明一下 ArgumentParser 這個好用的命令列參數設計。

看完這個篇章, 您會學到以下:

  • ArgumentParser的用途。
  • 自訂型態解析(Array)。
  • Boolean型態的處理。

什麼是「ArgumentParser」?

ArgumentParser是Python內建模組argparse所提供的類別, 它主要擔任的角色是提供我們設計出伺服端的互動式指令界面, 這麼說好了, 像是 nvitop 這套GPU監控工具:

# 我需要help...
nvitop -h
圖片來源

圖片來源

我們想查詢這個工具有什麼使用方式、參數時就可以鍵入「nvitop -h」來查詢, 就會有詳細的說明, 而這些說明在Python如何開發的呢? 其中一項內建模組類別就是「ArgumentParser」, 當然也有許多更強大的開源套件, 但我們會以內建來介紹就是不希望您太過發散, 基本概念如果能通,相信其他部份一定更快速上手。

基本用法

您可以根據「【🔒 Python 先修班】建立不害怕犯錯的開發環境(Docker + Docker Compose + Python + VSCode)」建立一個容易開發的Python環境, 並試著執行以下程式碼, 完成一個美好的開始。

# test.py

import argparse

# 創建一個ArgumentParser實例
parser = argparse.ArgumentParser(description='這是一個簡單的範例')

# 添加一個參數
parser.add_argument('--input', type=str, help='輸入檔案的路徑')

# 解析命令行參數
args = parser.parse_args()

# 使用解析後的參數
if args.input:
print(f'輸入檔案的路徑是:{args.input}')
else:
print('沒有提供輸入檔案的路徑')
python test.py -h

usage: test.py [-h] [--input INPUT]

這是一個簡單的範例

options:
-h, --help show this help message and exit
--input INPUT 輸入檔案的路徑

看起來有沒有很像專業級的套件程式, 沒錯, 這就是類似著名的命令列套件所設計的終端機互動式輸入介面, 接下來就讓各位自由發揮囉,自行設計出更多的命令列參數。

字串沒問題, 那陣列呢?

首先我們可能會很直覺的將type改為List, 以為這樣就解決了, 但事情沒有憨人所想的那麼簡單, 肯定有些貓膩的…

import argparse
from typing import List

parser.add_argument('--input', type=List[str], help='輸入檔案的路徑')

主要是因為使用者在輸入時遇到輸入某個參數多個值的狀況下, 通常會是以「,」隔開作為組與組之間的分隔, 然而這樣的需求之下, 我們就得設法將輸入參數進行分割處理了, 幸好, type的部份支援自訂型態的Callback回傳Function, 那我們就可以根據此特性來自行實作囉。

根據官方文件我們可以看到這一段話有提到自訂的函數可以被使用:

圖片來源

圖片來源

因此我們可以這樣設計:


def parse_list(val: str) -> List[str]:
return val.split(',')

parser.add_argument('--input', type=parse_list, help='請以逗號隔開進行多組輸入')

陣列也沒問題了, 那bool呢?

根據官方文件的記載, 我們可以看到「不建議使用 bool() 函數作為類型轉換器。 它所做的只是將空字符串轉換為 False,將非空字符串轉換為 True。 這通常不是所期望的。」, 看來bool不好處理啊…

圖片來源

圖片來源

讓我們換條思路, 既然bool的意義是決定是否開啟這樣的選項, 那麼我們翻翻action的部份,可以看到, 有條建議是關於 3.8+ 的這部分需要請您自行注意一下版本:

圖片來源

圖片來源

它其實設定該參數之後, 會自動將我們的Namespace分離成正與負的參數, 以「--foo」為例

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--foo', action=argparse.BooleanOptionalAction)

# 👀 注意看這邊, --foo會有「--foo」與「--no-foo」來讓使用者決定設定哪一個

結語

幸好Python的官方文檔非常給力啊, 該說明的都說明的非常細膩, 因此只要我們認真翻一翻其實都能夠得到我們要的解答, 不過沒有親自深入玩過還是不容易懂的, 所以這也是我們將筆記給分享出來的主要原因, 期望這樣的教學可以幫助到更多人。

喜歡撰寫文章的你,不妨來了解一下:

Web3.0時代下為創作者、閱讀者打造的專屬共贏平台 - 為什麼要加入?

歡迎加入一起練習寫作,賺取知識,累積財富!

91會員
260內容數
哈囉,我是阿Han,是一位 👩‍💻 軟體研發工程師,喜歡閱讀、學習、撰寫文章及教學,擅長以圖代文,化繁為簡,除了幫助自己釐清思路之外,也希望藉由圖解的方式幫助大家共同學習,甚至手把手帶您設計出高品質的軟體產品。
留言0
查看全部
發表第一個留言支持創作者!