Python में, argparse का उपयोग करते हुए, केवल सकारात्मक पूर्णांक की अनुमति दें


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उसके लिए मैन्युअल रूप से रूपांतरण करना चाहिए ?
15

4
@MrZ यह कुछ ऐसा देगा error: argument foo: invalid check_positive value: 'foo=<whatever>'। आप बस एक जोड़ सकते हैं try:... इसके except ValueError:चारों ओर जो बेहतर त्रुटि संदेश के साथ एक अपवाद को फिर से उठाता है।
युशि

59

type युसुशी के जवाब के अनुसार, स्थितियों / चेकों को संभालने के लिए अनुशंसित विकल्प होगा।

अपने विशिष्ट मामले में, आप choicesपैरामीटर का उपयोग कर सकते हैं यदि आपकी ऊपरी सीमा भी ज्ञात है:

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

नोट: अजगर 3.x के rangeबजाय का उपयोग करेंxrange


3
मुझे लगता है कि यह काफी अक्षम होगा, क्योंकि आप एक रेंज पैदा कर रहे होंगे और फिर इसके माध्यम से साइकिल चलाना आपके इनपुट को मान्य करेंगे। एक क्विक ifबहुत तेज है।
ट्रैविसथोमस

2
@ trav1th वास्तव में यह हो सकता है, लेकिन यह डॉक्स से एक उदाहरण का उपयोग है। इसके अलावा, मैंने अपने जवाब में कहा है कि युशी का जवाब है कि वह कहां जाए। विकल्प देने के लिए अच्छा है। और अर्गपर्स के मामले में, यह निष्पादन के बाद एक बार हो रहा है, एक जनरेटर ( xrange) का उपयोग करता है और अतिरिक्त कोड की आवश्यकता नहीं होती है। वह व्यापार बंद उपलब्ध है। हर एक को तय करना है कि किस रास्ते पर जाना है।
Aneroid

16
बेन लेखक के जवाब पर जगरिट्टी के बिंदु के बारे में स्पष्ट होने के लिए, विकल्प = xrange (0,1000) के परिणामस्वरूप पूर्णांक की पूरी सूची 1 से 999 तक आपके कंसोल पर हर बार जब आप उपयोग करते हैं - समावेशी हो या कोई अमान्य तर्क हो प्रदान की है। ज्यादातर परिस्थितियों में एक अच्छा विकल्प नहीं।
बायोमिकर

9

त्वरित और गंदे तरीके, अगर आपके पास अपने arg के लिए मिनट के साथ-साथ एक पूर्वानुमान योग्य अधिकतम है, तो choicesएक सीमा के साथ उपयोग किया जाता है

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

24
नकारात्मक पक्ष छिपा उत्पादन है।
jgritty

6
गंदे पर जोर , मुझे लगता है।
बेन लेखक

4
जग्रिट्टी के बिंदु के बारे में स्पष्ट होने के लिए, विकल्प = xrange (0,1000) का परिणाम होगा कि पूर्णांक की पूरी सूची 1 से 999 तक आपके कंसोल पर हर बार आपके द्वारा लिखे जा रहे समावेशी --help या यदि कोई अमान्य तर्क प्रदान की जाती है, लिखी जाएगी। ज्यादातर परिस्थितियों में एक अच्छा विकल्प नहीं।
बायोमिकर

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

यदि कोई व्यक्ति (मेरे जैसा) Google खोज में इस प्रश्न के पार आता है, तो यहां इस बात का एक उदाहरण है कि केवल एक निर्दिष्ट सीमा में आर्गेजर्स पूर्णांक की अनुमति देने की अधिक सामान्य समस्या को हल करने के लिए एक मॉड्यूलर दृष्टिकोण का उपयोग कैसे करें :

# 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
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.