python---argparse 解析 bool 值

runstone發表於2020-05-13

在一個需要用到flag作為訊號控制程式碼中一些程式碼片段是否執行的,比如”–flag True”或者”–flag False”。
但是古怪的是無法傳入False,無論傳入True還是False,程式裡面都是True的引數,所以這個flag並沒有生效,也就失去了意義。

參考程式碼:

# test.py
import argparse


def test_bool():
    parser = argparse.ArgumentParser(description="This code is used to test bool value.")
    parser.add_argument("--flag",
                        type=bool,
                        default=True)
    args = parser.parse_args()
    print("# The type of flag: ", type(args.flag))
    print(args.flag is False)

    if args.flag:
        print(f"# Flag: {True}")
    else:
        print(f"# Flag: {False}")


if __name__ == '__main__':
    test_bool()

執行上面的程式碼:python3 test.py --flag False
按照執行的期望是輸出# Flag: False,但是實際輸出的結果是True

(data_parse)  ~/Desktop/code/cython&numba  python3 test.py --flag False
# The type of flag:  <class 'bool'>
False
# Flag: True

為什麼會出現這種情況呢?因為,在命令列的輸入會被python認為是字串,並不是布林型別。

解決方式一【推薦】

更改程式碼為:

# ***
parser.add_argument("--flag",
                        action="store_true",
                        help="Run or not.")
# ***

這樣的話,當你不輸入--flag的時候,預設為False;輸入--flag的時候,才會觸發True值。
看執行結果:

(data_parse)  ~/Desktop/code/cython&numba  python3 test.py
# The type of flag:  <class 'bool'>
True
# Flag: False
(data_parse)  ~/Desktop/code/cython&numba  python3 test.py --flag
# The type of flag:  <class 'bool'>
False
# Flag: True

當然這種方式,你也可以指定action為store_false,不輸入的時候--flag預設True,輸入--flag觸發False

解決方式二

這種方式稍微複雜一些,就是需要自己去寫一個函式對輸入的字串值進行一個轉換,由字串轉換為布林值。
程式碼:

import argparse


def str2bool(v):
    if isinstance(v, bool):
        return v
    if v.lower() in ('yes', 'true', 't', 'y', '1'):
        return True
    elif v.lower() in ('no', 'false', 'f', 'n', '0'):
        return False
    else:
        raise argparse.ArgumentTypeError('Boolean value expected.')


def test_bool():
    parser = argparse.ArgumentParser(description="This code is used to test bool value.")
    parser.add_argument("--flag",
                        type=str2bool,
                        default=True,
                        help="Run or not.")
    args = parser.parse_args()
    print("# The type of flag: ", type(args.flag))
    print(args.flag is False)
    if args.flag:
        print(f"# Flag: {True}")
    else:
        print(f"# Flag: {False}")


if __name__ == '__main__':
    test_bool()

這樣的話,當我們只要輸入自定義函式中的那些對應TrueorFalse的選項,就能能觸發對應的布林型別。
看執行情況:

(data_parse)  ~/Desktop/code/cython&numba  python3 test.py         
# The type of flag:  <class 'bool'>
False
# Flag: True
(data_parse)  ~/Desktop/code/cython&numba  python3 test.py --flag True
# The type of flag:  <class 'bool'>
False
# Flag: True
(data_parse)  ~/Desktop/code/cython&numba  python3 test.py --flag False
# The type of flag:  <class 'bool'>
True
# Flag: False
(data_parse)  ~/Desktop/code/cython&numba  python3 test.py --flag 0    
# The type of flag:  <class 'bool'>
True
# Flag: False
(data_parse)  ~/Desktop/code/cython&numba  python3 test.py --flag 1
# The type of flag:  <class 'bool'>
False
# Flag: True

由於預設了default的值為True,所以不輸入--flag的時候就預設為True,然後輸入--flag對應自定義func: str2bool()中的選項時,就能達到想要的開關效果。

本作品採用《CC 協議》,轉載必須註明作者和本文連結
Stay hungry, stay foolish.

相關文章