পাইথনে, আরগপার্স ব্যবহার করে কেবল ইতিবাচক পূর্ণসংখ্যার অনুমতি দিন


164

শিরোনামটি বেশিরভাগ ক্ষেত্রে সংক্ষিপ্ত বিবরণ দেয় যা আমি ঘটতে চাই।

আমার কাছে যা আছে তা এখানেই রয়েছে এবং প্রোগ্রামটি কোনও অ-পজিটিভ পূর্ণসংখ্যার দিকে ঝাপিয়ে পড়ছে না, তবে আমি ব্যবহারকারীকে অবহিত করতে চাই যে একটি নন-পজিটিভ পূর্ণসংখ্যার মূলত বাজে কথা।

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("-g", "--games", type=int, default=162,
                    help="The number of games to simulate")
args = parser.parse_args()

এবং আউটপুট:

python simulate_many.py -g 20
Setting up...
Playing games...
....................

নেতিবাচক সাথে আউটপুট:

python simulate_many.py -g -2
Setting up...
Playing games...

এখন, স্পষ্টতই আমি ঠিক করতে পারলাম if args.gamesনেতিবাচক কিনা তা যোগ করতে পারতাম , তবে স্তরটিতে এটি ফাঁদ দেওয়ার কোনও উপায় থাকলে আমি আগ্রহী ছিলাম argparse, যাতে স্বয়ংক্রিয় ব্যবহারের মুদ্রণের সুবিধা নিতে পারে।

আদর্শভাবে, এটি এর অনুরূপ কিছু মুদ্রণ করবে:

python simulate_many.py -g a
usage: simulate_many.py [-h] [-g GAMES] [-d] [-l LEAGUE]
simulate_many.py: error: argument -g/--games: invalid int value: 'a'

তাই ভালো:

python simulate_many.py -g -2
usage: simulate_many.py [-h] [-g GAMES] [-d] [-l LEAGUE]
simulate_many.py: error: argument -g/--games: invalid positive int value: '-2'

আপাতত আমি এটি করছি, এবং অনুমান করি আমি খুশি:

if args.games <= 0:
    parser.print_help()
    print "-g/--games: must be positive."
    sys.exit(1)

উত্তর:


244

এটি সম্ভব ব্যবহার করা উচিত type। আপনাকে এখনও একটি আসল পদ্ধতিটি নির্ধারণ করতে হবে যা এটি আপনার জন্য সিদ্ধান্ত নেয়:

def check_positive(value):
    ivalue = int(value)
    if ivalue <= 0:
        raise argparse.ArgumentTypeError("%s is an invalid positive int value" % value)
    return ivalue

parser = argparse.ArgumentParser(...)
parser.add_argument('foo', type=check_positive)

এটি মুলত থেকে শুধু একটি অভিযোজিত উদাহরণ perfect_squareফাংশন ডক্স উপর argparse


1
আপনার ফাংশন একাধিক মান থাকতে পারে? ওটা কিভাবে কাজ করে?
টম

2
যদি রূপান্তর intব্যর্থ হয় তবে কী এখনও পঠনযোগ্য আউটপুট থাকবে? নাকি তার জন্য আপনাকে try raiseম্যানুয়ালি রূপান্তর করা উচিত ?
নোহস

4
@ মিঃজেড এটি এমন কিছু দেবে error: argument foo: invalid check_positive value: 'foo=<whatever>'। আপনি কেবল তার চারপাশে একটি try:... যুক্ত করতে except ValueError:পারেন যা আরও ভাল ত্রুটির বার্তা সহ একটি ব্যতিক্রম পুনরায় উত্থাপন করে।
Yuushi

59

type ইউউশির উত্তরের মতো শর্তগুলি / চেকগুলি পরিচালনা করার প্রস্তাব দেওয়া বিকল্প হবে।

আপনার নির্দিষ্ট ক্ষেত্রে, আপনি choicesযদি উচ্চতর সীমাটিও জেনে থাকেন তবে আপনি প্যারামিটারটিও ব্যবহার করতে পারেন :

parser.add_argument('foo', type=int, choices=xrange(5, 10))

দ্রষ্টব্য: পাইথন ৩.x এর rangeপরিবর্তে ব্যবহার করুনxrange


3
আমি ধারণা করি এটি মোটামুটি অদক্ষ হয়ে উঠবে, কারণ আপনি কোনও পরিসীমা তৈরি করবেন এবং তারপরে সাইকেল চালানো আপনার ইনপুটটিকে বৈধতা দেবে। একটি দ্রুত ifঅনেক দ্রুত।
ট্র্যাভিস থমাস

2
@ trav1th প্রকৃতপক্ষে এটি হতে পারে তবে এটি ডক্স থেকে ব্যবহারের একটি উদাহরণ। এছাড়াও, আমি আমার উত্তরে বলেছি যে ইউসীর উত্তরটিই তার পক্ষে যাওয়া উচিত। বিকল্প দেওয়া ভাল। আরগপার্সের ক্ষেত্রে, এটি কার্যকর হওয়ার পরে একবার হয়, একটি জেনারেটর ( xrange) ব্যবহার করে এবং অতিরিক্ত কোডের প্রয়োজন হয় না। যে বাণিজ্য বন্ধ আছে। প্রতিটি যে কোন পথে যেতে হবে তা স্থির করে নিন।
অ্যানেরয়েড

16
বেন লেখকের উত্তরের বিষয়ে জাগ্রিতির বক্তব্য সম্পর্কে আরও পরিস্কার হওয়ার জন্য, পছন্দগুলি = xrange (0,1000) এর ফলাফল হিসাবে আপনি প্রতিবার ব্যবহার করেন - হেল্প ব্যবহার করেন বা যদি কোনও অবৈধ যুক্তি হয় তবে আপনার কনসোলে 1 থেকে 999 সমেত পূর্ণসংখ্যার সম্পূর্ণ তালিকা তৈরি হবে or প্রদান করা হয়েছে। বেশিরভাগ পরিস্থিতিতে ভাল পছন্দ নয়।
বায়োমিকার

9

দ্রুত এবং নোংরা উপায়টি যদি আপনার আর্গুমেন্টের জন্য প্রডিক্টেবল সর্বাধিক পাশাপাশি কমপক্ষে থাকে তবে এটি choicesএকটি ব্যাপ্তির সাথে ব্যবহারযোগ্য

parser.add_argument('foo', type=int, choices=xrange(0, 1000))

24
অবক্ষয়টি হ'ল ঘৃণ্য আউটপুট।
jgritty

6
নোংরা উপর জোর , আমার ধারণা।
বেন লেখক

4
জগ্রিটিটির বিষয়টি সম্পর্কে আরও পরিষ্কার হওয়ার জন্য, পছন্দগুলি = এক্সরেঞ্জ (0,1000) এর ফলাফল হিসাবে আপনি প্রতিবার --help ব্যবহার করেন বা কোনও অবৈধ যুক্তি সরবরাহ করা হয় তবে আপনার কনসোলে 1 থেকে 999 অন্তর্ভুক্ত সহ পূর্ণসংখ্যার সম্পূর্ণ তালিকা তৈরি হবে। বেশিরভাগ পরিস্থিতিতে ভাল পছন্দ নয়।
বায়োমিকার

8

একটি সহজ বিকল্প, বিশেষত যদি সাবক্লাসিং argparse.ArgumentParserহয় তবে parse_argsপদ্ধতির অভ্যন্তর থেকে বৈধতা শুরু করা ।

এই জাতীয় একটি সাবক্লাসের ভিতরে:

def parse_args(self, args=None, namespace=None):
    """Parse and validate args."""
    namespace = super().parse_args(args, namespace)
    if namespace.games <= 0:
         raise self.error('The number of games must be a positive integer.')
    return namespace

এই কৌশলটি কাস্টম কলযোগ্য হিসাবে দুর্দান্ত নাও হতে পারে, তবে এটি কাজটি করে।


সম্পর্কে ArgumentParser.error(message):

এই পদ্ধতিটি স্ট্যান্ডার্ড ত্রুটির সাথে বার্তা সহ একটি ব্যবহারের বার্তা প্রিন্ট করে এবং 2 এর স্থিতি কোড সহ প্রোগ্রামটি সমাপ্ত করে।


ক্রেডিট: জনাটনের উত্তর


বা খুব কমপক্ষে, ন্যায়বিচারের সাথে প্রতিস্থাপন print "-g/--games: must be positive."; sys.exit(1)করা parser.error("-g/--games: must be positive.")( জোনাটনের উত্তরের মতো ব্যবহার ।)
অ্যারয়েড

3

যদি গুগল অনুসন্ধানে কেউ (আমার মতো) এই প্রশ্নটি আসে, কেবলমাত্র একটি নির্দিষ্ট পরিসরে আরগপার্স পূর্ণসংখ্যার অনুমতি দেওয়ার আরও সাধারণ সমস্যার ঝরঝরে সমাধান করার জন্য একটি মডুলার পদ্ধতির ব্যবহারের উদাহরণ এখানে রয়েছে :

# Custom argparse type representing a bounded int
class IntRange:

    def __init__(self, imin=None, imax=None):
        self.imin = imin
        self.imax = imax

    def __call__(self, arg):
        try:
            value = int(arg)
        except ValueError:
            raise self.exception()
        if (self.imin is not None and value < self.imin) or (self.imax is not None and value > self.imax):
            raise self.exception()
        return value

    def exception(self):
        if self.imin is not None and self.imax is not None:
            return argparse.ArgumentTypeError(f"Must be an integer in the range [{self.imin}, {self.imax}]")
        elif self.imin is not None:
            return argparse.ArgumentTypeError(f"Must be an integer >= {self.imin}")
        elif self.imax is not None:
            return argparse.ArgumentTypeError(f"Must be an integer <= {self.imax}")
        else:
            return argparse.ArgumentTypeError("Must be an integer")

এটি আপনাকে এর মতো কিছু করতে দেয়:

parser = argparse.ArgumentParser(...)
parser.add_argument('foo', type=IntRange(1))     # Must have foo >= 1
parser.add_argument('bar', type=IntRange(1, 7))  # Must have 1 <= bar <= 7

ভেরিয়েবলটি fooকেবল ইতিবাচক পূর্ণসংখ্যার অনুমতি দেয় , যেমন ওপি জিজ্ঞাসা করেছিল।

নোট করুন যে উপরের ফর্মগুলি ছাড়াও, কেবলমাত্র সর্বাধিক দ্বারা এটিও সম্ভব IntRange:

parser.add_argument('other', type=IntRange(imax=10))  # Must have other <= 10
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.