जब कोई तर्क के बिना स्क्रिप्ट को बुलाया जाता है तो अजगर संदेश के साथ मदद संदेश प्रदर्शित करें


226

यह एक सरल हो सकता है। मान लें कि मेरे पास एक प्रोग्राम है जो कमांड लाइन के तर्कों / विकल्पों को संसाधित करने के लिए argparse का उपयोग करता है। निम्नलिखित 'सहायता' संदेश मुद्रित करेगा:

./myprogram -h

या:

./myprogram --help

लेकिन, अगर मैं स्क्रिप्ट को बिना किसी तर्क के चलाता हूं, तो यह कुछ भी नहीं करता है। जब मैं चाहता हूं कि यह उपयोग संदेश प्रदर्शित करना है जब इसे बिना किसी तर्क के कहा जाता है। कैसे किया जाता है?

जवाबों:


273

यह जवाब Google समूहों पर स्टीवन बेथर्ड से आया है । मैं इसे यहाँ पा रहा हूँ ताकि बिना Google खाते के लोगों तक पहुँच आसान हो सके।

आप errorविधि के डिफ़ॉल्ट व्यवहार को ओवरराइड कर सकते हैं :

import argparse
import sys

class MyParser(argparse.ArgumentParser):
    def error(self, message):
        sys.stderr.write('error: %s\n' % message)
        self.print_help()
        sys.exit(2)

parser = MyParser()
parser.add_argument('foo', nargs='+')
args = parser.parse_args()

ध्यान दें कि उपरोक्त समाधान जब भी error विधि ट्रिगर होता है, मदद संदेश को प्रिंट करेगा । उदाहरण के लिए, test.py --blahमदद संदेश को प्रिंट करेगा भले ही --blahएक वैध विकल्प न हो।

यदि आप मदद संदेश को केवल तभी प्रिंट करना चाहते हैं जब कमांड लाइन पर कोई तर्क नहीं दिया जाता है, तो शायद यह अभी भी सबसे आसान तरीका है:

import argparse
import sys

parser=argparse.ArgumentParser()
parser.add_argument('foo', nargs='+')
if len(sys.argv)==1:
    parser.print_help(sys.stderr)
    sys.exit(1)
args=parser.parse_args()

ध्यान दें कि parser.print_help()डिफ़ॉल्ट रूप से स्टडआउट करने के लिए प्रिंट करता है। जैसा कि init_js सुझाता है , parser.print_help(sys.stderr)stderr पर प्रिंट करने के लिए उपयोग करें।


हाँ .. कि मैं क्या सोच रहा था, क्या इस परिदृश्य को संभालने के लिए एक प्रकार का तर्क था। धन्यवाद!
मुंशीएक्सएक्सएक्सएक्स

6
दूसरे समाधान में मैं इसके parser.print_usage()स्थान पर उपयोग करता हूं parser.print_help()- सहायता संदेश में उपयोग शामिल है लेकिन यह अधिक क्रिया है।
user2314737

5
मैंने जवाब के दूसरे भाग के लिए मतदान किया होगा, लेकिन ओवरराइडिंग error()मुझे एक भयानक विचार लगता है। यह एक अलग उद्देश्य प्रदान करता है, यह एक अनुकूल उपयोग या सहायता को मुद्रित करने के लिए डिज़ाइन नहीं किया गया है।
पीटरिनो

@Peterino - ओवरराइड एक बाल वर्ग में हो रहा है, इसलिए यह एक समस्या नहीं होनी चाहिए। यह स्पष्ट है।
मार्सेल विल्सन

1
@unutbu चमत्कारिक! बिल्कुल वही जो मुझे चाहिए था। एक सवाल यह है कि क्या यह सबकॉमैंड्स पर भी लागू हो सकता है? मुझे आमतौर पर सिर्फ `` नेमस्पेस (आउटपुट = कोई नहीं) `मिलता है। मैं सभी सबकॉमैंड पर आसानी से त्रुटि कैसे ट्रिगर कर सकता हूं? मैं वहाँ एक त्रुटि ट्रिगर करना चाहता हूँ।
जोनाथन कोमर

56

कक्षा लिखने के बजाय, एक कोशिश / छोड़कर उपयोग किया जा सकता है

try:
    options = parser.parse_args()
except:
    parser.print_help()
    sys.exit(0)

उल्टा यह है कि वर्कफ़्लो स्पष्ट है और आपको स्टब क्लास की आवश्यकता नहीं है। नकारात्मक पक्ष यह है कि पहली 'उपयोग' लाइन दो बार मुद्रित होती है।

इसके लिए कम से कम एक अनिवार्य तर्क की आवश्यकता होगी। अनिवार्य तर्कों के साथ, कमांडलाइन पर शून्य आर्ग प्रदान करना मान्य है।


मुझे भी, मैं स्वीकृत उत्तर के लिए इसे पसंद करता हूं। जब तर्क अनपेक्षित होते हैं, तो मुद्रण सहायता के लिए एक वर्ग जोड़ना अतिदेय है। उत्कृष्ट मॉड्यूल को आप के लिए त्रुटि मामलों को संभालने दें।
निकोल फिनी

7
यदि -hध्वज का उपयोग किया जाता है तो यह कोड प्रिंट में 2 बार मदद करता है, और यदि --versionध्वज का उपयोग किया जाता है तो अनावश्यक प्रिंट मदद करते हैं। उन समस्याओं को कम करने के लिए आप इस तरह की त्रुटि प्रकार की जाँच कर सकते हैं:except SystemExit as err: if err.code == 2: parser.print_help()
pkowalczyk

25

आप कर सकते हैं:

parser.argparse.ArgumentParser()
#parser.add_args here

#sys.argv includes a list of elements starting with the program
if len(sys.argv) < 2:
    parser.print_usage()
    sys.exit(1)

5
यह कॉल करने से पहले आना चाहिएparser.parse_args()
बॉब स्टीन

18

यदि आपके पास तर्क हैं जिन्हें चलाने के लिए स्क्रिप्ट के लिए निर्दिष्ट किया जाना चाहिए - नीचे दिए गए अनुसार ArgumentParser के लिए आवश्यक पैरामीटर का उपयोग करें: -

parser.add_argument('--foo', required=True)

यदि स्क्रिप्ट बिना किसी तर्क के चलाई जाती है, तो parse_args () एक त्रुटि की सूचना देगा।


2
यह सबसे सरल उपाय है और यह निर्दिष्ट अवैध विकल्पों के साथ भी काम करेगा।
स्टीव शायर

1
माना। मुझे लगता है कि तर्क पार्सर की अंतर्निहित क्षमताओं का लाभ उठाना हमेशा बेहतर होता है, फिर किसी तरह का एक अतिरिक्त हैंडलर लिखना।
क्रिस्टोफर हंटर

18

यदि आप (उप) पार्सर्स के लिए डिफ़ॉल्ट फ़ंक्शंस को संबद्ध करते हैं, जैसा कि नीचे बताया गया है add_subparsers, तो आप बस इसे डिफ़ॉल्ट एक्शन के रूप में जोड़ सकते हैं:

parser = argparse.ArgumentParser()
parser.set_defaults(func=lambda x: parser.print_usage())
args = parser.parse_args()
args.func(args)

यदि आप स्थितीय तर्कों के कारण अपवादों को उठाते हैं, तो प्रयास को छोड़कर।


1
यह जवाब इतना कम आंका गया है। सरल और उप-पार्सर के साथ बहुत अच्छी तरह से काम करता है।
orodbhen

बहुत बढ़िया जवाब! एकमात्र परिवर्तन जो मैंने किया था वह पैरामीटर के बिना लंबो का उपयोग कर रहा था।
बोह 717

12

सबसे साफ समाधान डिफ़ॉल्ट तर्क को मैन्युअल रूप से पारित करना होगा यदि कमांड लाइन पर कोई भी नहीं दिया गया था:

parser.parse_args(args=None if sys.argv[1:] else ['--help'])

पूरा उदाहरण:

import argparse, sys

parser = argparse.ArgumentParser()
parser.add_argument('--host', default='localhost', help='Host to connect to')
# parse arguments
args = parser.parse_args(args=None if sys.argv[1:] else ['--help'])

# use your args
print("connecting to {}".format(args.host))

यदि w / o तर्क कहा जाता है, तो यह पूरी मदद (लघु उपयोग नहीं) मुद्रित करेगा।


2
sys.argv[1:]एक बहुत ही सामान्य मुहावरा है। मैं parser.parse_args(None if sys.argv[1:] else ['-h'])अधिक मुहावरेदार और साफ-सुथरा दिखता हूं ।
नूनो एंड्रे

1
@ NunoAndré धन्यवाद - जवाब अद्यतन। वास्तव में अधिक पायथोनिक लगता है।
इवगेन पोपोविच

10

यहाँ मेरे संस्करण को ढेर में फेंकना:

import argparse

parser = argparse.ArgumentParser()
args = parser.parse_args()
if not vars(args):
    parser.print_help()
    parser.exit(1)

आप नोटिस कर सकते हैं parser.exit- मैं इसे मुख्य रूप से ऐसा करता हूं क्योंकि यह एक आयात लाइन को बचाता है अगर वह sysफ़ाइल का एकमात्र कारण था ...


parser.exit (1) अच्छा है! अच्छा जोड़।
cgseller

4
दुर्भाग्यवश parser.parse_args () से बाहर निकल जाएगा यदि एक स्थिति संबंधी तर्क गायब है। तो यह केवल वैकल्पिक तर्कों का उपयोग करते समय काम करता है।
मार्सेल विल्सन

1
@ मार्सेलविल्स, यह वास्तव में करता है - अच्छी पकड़! मैं इस बारे में सोचूंगा कि इसे कैसे बदला जाए।
पौरिचेलोडिगर

not vars(args)जब तर्क की defaultविधि हो तो काम नहीं कर सकते ।
फनकिड

5

एक लाइनर्स की एक जोड़ी होती है sys.argv[1:](कमांड लाइन के तर्कों का उल्लेख करने के लिए एक बहुत ही सामान्य पायथन का मुहावरा, sys.argv[0]स्क्रिप्ट का नाम होने के नाते ) जो काम कर सकता है।

पहले एक स्व-व्याख्यात्मक, स्वच्छ और पायथोनिक है:

args = parser.parse_args(None if sys.argv[1:] else ['-h'])

दूसरा छोटा हैकर है। पहले से मूल्यांकन किए गए तथ्य को जोड़ना कि एक खाली सूची आपके पास है और समकक्षों के Falseसाथ :True == 1False == 0

args = parser.parse_args([None, ['-h']][not sys.argv[1:]])

हो सकता है कि बहुत सारे ब्रैकेट, लेकिन बहुत स्पष्ट हो अगर पिछले तर्क का चयन किया गया था।

_, *av = sys.argv
args = parser.parse_args([None, ['-h']][not av])

1
parser.print_help()
parser.exit()

parser.exitविधि को भी एक को स्वीकार status(returncode), और एक messageमूल्य (ट्रेलिंग न्यू लाइन अपने आप को शामिल!)।

एक स्पष्ट उदाहरण, :)

#!/usr/bin/env python3

""" Example argparser based python file
"""

import argparse

ARGP = argparse.ArgumentParser(
    description=__doc__,
    formatter_class=argparse.RawTextHelpFormatter,
)
ARGP.add_argument('--example', action='store_true', help='Example Argument')


def main(argp=None):
    if argp is None:
        argp = ARGP.parse_args()  # pragma: no cover

    if 'soemthing_went_wrong' and not argp.example:
        ARGP.print_help()
        ARGP.exit(status=128, message="\nI just don't know what went wrong, maybe missing --example condition?\n")


if __name__ == '__main__':
    main()  # pragma: no cover

उदाहरण कॉल:

$ python3 ~ / helloworld.py; इको $?
उपयोग: helloworld.py [-h] [--example]

 उदाहरण argparser आधारित अजगर फ़ाइल

वैकल्पिक तर्क:
  -h, --help यह मदद संदेश और बाहर निकलने को दिखाता है
  - उदाहरण नमूना तर्क

मैं अभी नहीं जानता कि क्या गलत हो गया है, शायद गायब --निष्ठ स्थिति?
128
$ python3 ~ / helloworld.py --example; इको $?
0

0

अपने स्थिति संबंधी तर्कों को नर्गों के साथ सेट करें, और जांचें कि क्या स्थितिगत आर्गन खाली हैं।

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('file', nargs='?')
args = parser.parse_args()
if not args.file:
    parser.print_help()

संदर्भ पायथन ने सुनाया


0

इसे करने का एक और तरीका है, यदि आपको किसी लचीली चीज़ की ज़रूरत है जहाँ आप मदद प्रदर्शित करना चाहते हैं यदि कोई विशिष्ट पैरामस पास हो, तो कोई भी या 1 से अधिक परस्पर विरोधी arg:

import argparse
import sys

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('-d', '--days', required=False,  help="Check mapped inventory that is x days old", default=None)
    parser.add_argument('-e', '--event', required=False, action="store", dest="event_id",
                        help="Check mapped inventory for a specific event", default=None)
    parser.add_argument('-b', '--broker', required=False, action="store", dest="broker_id",
                        help="Check mapped inventory for a broker", default=None)
    parser.add_argument('-k', '--keyword', required=False, action="store", dest="event_keyword",
                        help="Check mapped inventory for a specific event keyword", default=None)
    parser.add_argument('-p', '--product', required=False, action="store", dest="product_id",
                        help="Check mapped inventory for a specific product", default=None)
    parser.add_argument('-m', '--metadata', required=False, action="store", dest="metadata",
                        help="Check mapped inventory for specific metadata, good for debugging past tix", default=None)
    parser.add_argument('-u', '--update', required=False, action="store_true", dest="make_updates",
                        help="Update the event for a product if there is a difference, default No", default=False)
    args = parser.parse_args()

    days = args.days
    event_id = args.event_id
    broker_id = args.broker_id
    event_keyword = args.event_keyword
    product_id = args.product_id
    metadata = args.metadata
    make_updates = args.make_updates

    no_change_counter = 0
    change_counter = 0

    req_arg = bool(days) + bool(event_id) + bool(broker_id) + bool(product_id) + bool(event_keyword) + bool(metadata)
    if not req_arg:
        print("Need to specify days, broker id, event id, event keyword or past tickets full metadata")
        parser.print_help()
        sys.exit()
    elif req_arg != 1:
        print("More than one option specified. Need to specify only one required option")
        parser.print_help()
        sys.exit()

    # Processing logic here ...

चीयर्स!


मुझे लगता है कि आप बहुत आसान होगा कि आप subparsers या mutually_exclusive_group का उपयोग करें
टिम ब्रे

0

यदि आपका कमांड कुछ ऐसा है जहां उपयोगकर्ता को कुछ कार्रवाई चुनने की आवश्यकता है, तो आवश्यक = सत्य के साथ पारस्परिक रूप से अनन्य समूह का उपयोग करें ।

यह pd321 द्वारा दिए गए उत्तर के विस्तार की तरह है।

import argparse

parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument("--batch", action='store', type=int,  metavar='pay_id')
group.add_argument("--list", action='store_true')
group.add_argument("--all", action='store_true', help='check all payments')

args=parser.parse_args()

if args.batch:
    print('batch {}'.format(args.batch))

if args.list:
    print('list')

if args.all:
    print('all')

आउटपुट:

$ python3 a_test.py
उपयोग: a_test.py [-h] (--batch pay_id | --list .-
all ) a_test.py: error: one of the तर्क --batch --list-all

इससे केवल मूल मदद मिलती है। और कुछ अन्य उत्तर आपको पूरी मदद करेंगे। लेकिन कम से कम आपके उपयोगकर्ता जानते हैं कि वे कर सकते हैं -एच


0

यह अच्छा नहीं है (क्योंकि, सभी त्रुटियों को स्वीकार करता है), लेकिन:

def _error(parser):
    def wrapper(interceptor):
        parser.print_help()

        sys.exit(-1)

    return wrapper

def _args_get(args=sys.argv[1:]):
    parser = argparser.ArgumentParser()

    parser.error = _error(parser)

    parser.add_argument(...)
    ...

यहाँ कक्षा के errorकार्य की परिभाषा है ArgumentParser:

https://github.com/python/cpython/blob/276eb67c29d05a93fbc22eea5470282e73700d20/Lib/argparse.py#L2374

। जैसा कि आप देखते हैं, हस्ताक्षर के बाद, यह दो तर्क लेता है। हालाँकि, कक्षा के बाहर के कार्य पहले तर्क के बारे में कुछ भी नहीं जानते हैं: selfक्योंकि, मोटे तौर पर, यह कक्षा के लिए पैरामीटर है। (मुझे पता है, कि तुम्हें पता है ...) जिससे, बस पास selfऔर खुद messageमें _error(...)नहीं है (

def _error(self, message):
    self.print_help()

    sys.exit(-1)

def _args_get(args=sys.argv[1:]):
    parser = argparser.ArgumentParser()

    parser.error = _error
    ...
...

उत्पादन होगा:

...
"AttributeError: 'str' object has no attribute 'print_help'"

)। आप इसे कॉल करके फ़ंक्शन में parser( self) पास कर सकते हैं _error:

def _error(self, message):
    self.print_help()

    sys.exit(-1)

def _args_get(args=sys.argv[1:]):
    parser = argparser.ArgumentParser()

    parser.error = _error(parser)
    ...
...

, लेकिन आप अभी कार्यक्रम से बाहर नहीं जाना चाहते हैं। फिर इसे वापस करें:

def _error(parser):
    def wrapper():
        parser.print_help()

        sys.exit(-1)

    return wrapper
...

। बहरहाल, parserयह नहीं जानता कि इसे संशोधित किया गया है, इस प्रकार जब कोई त्रुटि होती है, तो वह इसका कारण (वैसे, इसका स्थानीय अनुवाद) भेजेगा। ठीक है, तो इसे रोकें:

def _error(parser):
    def wrapper(interceptor):
        parser.print_help()

        sys.exit(-1)

    return wrapper
...

। अब, जब त्रुटि होती है और parserइसका कारण भेजेंगे, तो आप इसे रोकेंगे, इसे देखें, और ... बाहर फेंक दें।

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