874

「--foo True」または「--foo False」として記述されたブール値のコマンドライン引数を解析するために argparse を使用したいと考えています。例えば:

my_program --my_boolean_flag False

ただし、次のテスト コードは、私が望むことを行いません。

import argparse
parser = argparse.ArgumentParser(description="My parser")
parser.add_argument("--my_bool", type=bool)
cmd_line = ["--my_bool", "False"]
parsed_args = parser.parse(cmd_line)

悲しいことに、 にparsed_args.my_bool評価されTrueます。cmd_lineこれは、 が に評価されるため、に変更した場合でも当てはまります。["--my_bool", ""]これは驚くべきことです。bool("")False

"False""F"、およびそれらの小文字のバリアントをに解析する argparse を取得するにはどうすればよいFalseですか?

4

23 に答える 23

1178

これを行うためのより標準的な方法は、次のとおりだと思います。

command --feature

command --no-feature

argparseこのバージョンをうまくサポートします:

Python 3.9+ :

parser.add_argument('--feature', action=argparse.BooleanOptionalAction)

Python < 3.9:

parser.add_argument('--feature', action='store_true')
parser.add_argument('--no-feature', action='store_false')
parser.set_defaults(feature=True)

もちろん、本当にバージョンが必要な場合は、「タイプ」またはユーザー定義関数として--arg <True|False>渡すことができます...ast.literal_eval

def t_or_f(arg):
    ua = str(arg).upper()
    if 'TRUE'.startswith(ua):
       return True
    elif 'FALSE'.startswith(ua):
       return False
    else:
       pass  #error condition maybe?
于 2013-02-21T17:40:24.810 に答える
106

これは、デフォルト値を設定するための追加の行がない別のバリエーションです。ブール値は常に割り当てられるため、事前にチェックせずに論理ステートメントで使用できます。

import argparse
parser = argparse.ArgumentParser(description="Parse bool")
parser.add_argument("--do-something", default=False, action="store_true",
                    help="Flag to do something")
args = parser.parse_args()

if args.do_something:
     print("Do something")
else:
     print("Don't do something")

print(f"Check that args.do_something={args.do_something} is always a bool.")
于 2016-05-24T11:16:24.247 に答える
18

私は同じ問題を探していましたが、かなりの解決策は次のとおりです。

def str2bool(v):
  return v.lower() in ("yes", "true", "t", "1")

上記のように、それを使用して文字列をブール値に解析します。

于 2013-10-07T14:20:38.340 に答える
13

@mgilsonが言ったことに加えて、それを強制するのを簡単にし、同時に使用されない方法もあることに注意してArgumentParser.add_mutually_exclusive_group(required=False)ください。--flag--no-flag

于 2014-03-28T04:20:17.473 に答える
12

最も単純です。柔軟ではありませんが、私はシンプルさを好みます。

  parser.add_argument('--boolean_flag',
                      help='This is a boolean flag.',
                      type=eval, 
                      choices=[True, False], 
                      default='True')

編集:入力が信頼できない場合は、使用しないでくださいeval

于 2020-04-03T16:51:13.990 に答える
11

これは実際には時代遅れです。Python 3.7 以降では、Argparse がブール値の引数をサポートするようになりました (BooleanOptionalAction を検索)。

実装は次のようになります。

import argparse

ap = argparse.ArgumentParser()

# List of args
ap.add_argument('--foo', default=True, type=bool, help='Some helpful text that is not bar. Default = True')

# Importable object
args = ap.parse_args()

もう 1 つ言及する必要があります。これにより、argparse.ArgumentTypeError を介して、引数の True と False 以外のすべてのエントリがブロックされます。何らかの理由でこれを変更したい場合は、カスタム エラー クラスを作成できます。

于 2021-08-20T20:22:47.640 に答える
8

より簡単な方法は、以下のように使用することです。

parser.add_argument('--feature', type=lambda s: s.lower() in ['true', 't', 'yes', '1'])
于 2016-12-27T05:44:03.120 に答える
0

Similar to @Akash but here is another approach that I've used. It uses str than lambda because python lambda always gives me an alien-feelings.

import argparse
from distutils.util import strtobool

parser = argparse.ArgumentParser()
parser.add_argument("--my_bool", type=str, default="False")
args = parser.parse_args()

if bool(strtobool(args.my_bool)) is True:
    print("OK")
于 2020-04-27T06:20:00.700 に答える
0
class FlagAction(argparse.Action):
    # From http://bugs.python.org/issue8538

    def __init__(self, option_strings, dest, default=None,
                 required=False, help=None, metavar=None,
                 positive_prefixes=['--'], negative_prefixes=['--no-']):
        self.positive_strings = set()
        self.negative_strings = set()
        for string in option_strings:
            assert re.match(r'--[A-z]+', string)
            suffix = string[2:]
            for positive_prefix in positive_prefixes:
                self.positive_strings.add(positive_prefix + suffix)
            for negative_prefix in negative_prefixes:
                self.negative_strings.add(negative_prefix + suffix)
        strings = list(self.positive_strings | self.negative_strings)
        super(FlagAction, self).__init__(option_strings=strings, dest=dest,
                                         nargs=0, const=None, default=default, type=bool, choices=None,
                                         required=required, help=help, metavar=metavar)

    def __call__(self, parser, namespace, values, option_string=None):
        if option_string in self.positive_strings:
            setattr(namespace, self.dest, True)
        else:
            setattr(namespace, self.dest, False)
于 2014-10-28T21:00:19.290 に答える