python - Argparse সঙ্গে বুলিয়ান মান পার্সিং




boolean command-line-parsing (9)

আমি "--ফু ট্রু" বা "--ফু মিথ্যা" হিসাবে লিখিত বুলিয়ান কমান্ড-লাইন আর্গুমেন্টগুলিকে পার্স করতে আর্গপার্স ব্যবহার করতে চাই। উদাহরণ স্বরূপ:

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 মূল্যায়ন করে। এই ক্ষেত্রেই cmd_line পরিবর্তন করতে cmd_line ["--my_bool", ""] , যা বিস্ময়কর, কারণ bool("") False বিকৃত হয়।

কিভাবে আমি "False" , "F" , এবং তাদের নিম্নতর-কেসের রূপগুলিকে "False" বলার জন্য আর্গুমেন্ট পেতে পারি?


@ মিজিলসন ছাড়াও, এটি উল্লেখ করা উচিত যে সেখানে একটি ArgumentParser.add_mutually_exclusive_group(required=False) পদ্ধতি রয়েছে যা এটি কার্যকর করার জন্য --flag --no-flag এবং --no-flag একই সময়ে ব্যবহার করা হয় না ।


আমি mgilson এর উত্তর সুপারিশ কিন্তু একটি পারস্পরিক একচেটিয়া গ্রুপ সঙ্গে
যাতে আপনি একই সময়ে --no-feature এবং --no-feature ব্যবহার করতে পারবেন না।

command --feature

এবং

command --no-feature

কিন্তু না

command --feature --no-feature

লিপি:

feature_parser = parser.add_mutually_exclusive_group(required=False)
feature_parser.add_argument('--feature', dest='feature', action='store_true')
feature_parser.add_argument('--no-feature', dest='feature', action='store_false')
parser.set_defaults(feature=True)

আপনি যদি তাদের অনেকগুলি সেট করতে যাচ্ছেন তবে আপনি এই সহায়কটি ব্যবহার করতে পারেন:

def add_bool_arg(parser, name, default=False):
    group = parser.add_mutually_exclusive_group(required=False)
    group.add_argument('--' + name, dest=name, action='store_true')
    group.add_argument('--no-' + name, dest=name, action='store_false')
    parser.set_defaults(**{name:default})

add_bool_arg(parser, 'useful-feature')
add_bool_arg(parser, 'even-more-useful-feature')

আমি মনে করি এর মাধ্যমে আরো একটি ক্যাননিক্যাল উপায় হল:

command --feature

এবং

command --no-feature

argparse চমত্কারভাবে এই সংস্করণ সমর্থন করে:

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

অবশ্যই, যদি আপনি সত্যিই --arg <True|False> সংস্করণটি চান তবে আপনি ast.literal_eval "type", বা ব্যবহারকারীর সংজ্ঞায়িত ফাংশন হিসাবে পাস করতে পারেন ...

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?

আমি মনে করি সবচেয়ে ক্যাননিক উপায় হবে:

parser.add_argument('--ensure', nargs='*', default=None)

ENSURE = config.ensure is None

এক রৈখিক:

parser.add_argument('--is_debug', default=False, type=lambda x: (str(x).lower() == 'true'))

একটি বেশ অনুরূপ উপায় ব্যবহার করা হয়:

feature.add_argument('--feature',action='store_true')

এবং যদি আপনি আপনার কমান্ডের মধ্যে যুক্তি - বৈশিষ্ট্য সেট করেন

 command --feature

যুক্তিটি সত্য হবে, যদি আপনি টাইপ -ফেক্ট সেট না করেন তবে আর্গুমেন্ট ডিফল্ট সর্বদা মিথ্যা!


এখানে ডিফল্ট মান সেট করার জন্য অতিরিক্ত সারি / গুলি ছাড়া অন্য বৈচিত্র্য। বোলে সর্বদা একটি মান নির্ধারিত থাকে যাতে এটি পূর্ব-চেক ছাড়া লজিক্যাল বিবৃতিগুলিতে ব্যবহার করা যেতে পারে।

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 == True:
     print("Do something")
else:
     print("Don't do something")
print("Check that args.do_something=" + str(args.do_something) + " is always a bool")

কোন type=bool বিভ্রান্তি বলে মনে হচ্ছে type=bool এবং type='bool' মানে হতে পারে। এক (বা উভয়) অর্থ 'ফাংশন bool() , বা' একটি বুলিয়ান ফেরত 'চালানো উচিত? যেমনটি দাঁড়িয়ে থাকে type='bool' মানে কিছুই না। add_argument দেয় একটি 'bool' is not callable ত্রুটি নয়, একইভাবে আপনি type='foobar' , বা type='int'

কিন্তু argparse আপনি এই মত কীওয়ার্ড সংজ্ঞায়িত করতে দেয় যে রেজিস্ট্রি আছে। এটি বেশিরভাগই action জন্য ব্যবহৃত হয়, যেমন `action = 'store_true'। আপনি নিবন্ধিত কীওয়ার্ড দেখতে পারেন:

parser._registries

যা একটি অভিধান প্রদর্শন করে

{'action': {None: argparse._StoreAction,
  'append': argparse._AppendAction,
  'append_const': argparse._AppendConstAction,
...
 'type': {None: <function argparse.identity>}}

অনেকগুলি কর্ম সংজ্ঞায়িত করা হয়েছে, তবে শুধুমাত্র একটি প্রকার, ডিফল্ট এক, argparse.identity

এই কোডটি একটি 'বোল' কীওয়ার্ড সংজ্ঞায়িত করে:

def str2bool(v):
  #susendberg's function
  return v.lower() in ("yes", "true", "t", "1")
p = argparse.ArgumentParser()
p.register('type','bool',str2bool) # add type keyword to registries
p.add_argument('-b',type='bool')  # do not use 'type=bool'
# p.add_argument('-b',type=str2bool) # works just as well
p.parse_args('-b false'.split())
Namespace(b=False)

parser.register() নথিভুক্ত নয়, তবে লুকানো নেই। অধিকাংশ অংশে প্রোগ্রামারকে এটি সম্পর্কে জানতে হবে না কারণ type এবং action ফাংশন এবং বর্গ মানগুলি গ্রহণ করে। উভয় জন্য কাস্টম মান সংজ্ঞায়িত স্ট্যাকভারফ্লো উদাহরণ প্রচুর আছে।

পূর্বের আলোচনার থেকে এটি সুস্পষ্ট না হলে, bool() অর্থ একটি স্ট্রিং বিশ্লেষণ করে না। পাইথন ডকুমেন্টেশন থেকে:

bool (x): মান সত্য পরীক্ষার পদ্ধতি ব্যবহার করে একটি বুলিয়ানের মানটি রূপান্তর করুন।

সঙ্গে এই বিপরীতে

int (x): একটি সংখ্যা বা স্ট্রিং এক্স একটি পূর্ণসংখ্যাতে রূপান্তর করুন।


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)




command-line-parsing