কোনও আর্গুমেন্ট ছাড়াই স্ক্রিপ্ট কল করা হলে পাইথন আরগপার্সে সাহায্যের বার্তা প্রদর্শন করুন


226

এটি একটি সহজ এক হতে পারে। ধরুন আমার কাছে একটি প্রোগ্রাম রয়েছে যা কমান্ড লাইন আর্গুমেন্ট / বিকল্পগুলি প্রক্রিয়া করতে আরগপার্স ব্যবহার করে। নিম্নলিখিতগুলি 'সহায়তা' বার্তাটি মুদ্রণ করবে:

./myprogram -h

বা:

./myprogram --help

তবে, আমি যদি কোনও যুক্তি ছাড়াই স্ক্রিপ্টটি চালাই তবে এটি কিছুই করে না। আমি এটি করতে চাই তা হ'ল ব্যবহারের বার্তাটি প্রদর্শন করা যখন এটি কোনও যুক্তি ছাড়াই ডাকা হয়। কীভাবে হয়?

উত্তর:


273

এই উত্তরটি গুগল গ্রুপগুলির স্টিভেন বেথার্ডের কাছ থেকে এসেছে । গুগল অ্যাকাউন্ট ছাড়া লোকের অ্যাক্সেস করা আরও সহজ করার জন্য আমি এটি এখানে পুনরায় পোস্ট করছি ost

আপনি 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 হবে প্রিন্ট করতে।


হ্যাঁ ... এই বিষয়টি নিয়েই আমি ভাবছিলাম, এই পরিস্থিতিটি পরিচালনা করার জন্য আরগপার্সের কোনও উপায় ছিল কিনা। ধন্যবাদ!
musashiXXX

6
দ্বিতীয় সমাধানে আমি parser.print_usage()এর স্থলে ব্যবহার করি parser.print_help()- সহায়তা বার্তায় ব্যবহার অন্তর্ভুক্ত রয়েছে তবে এটি আরও ভার্বোস।
ব্যবহারকারী 2314737

5
আমি উত্তরের দ্বিতীয় অংশের পক্ষে ভোট দিয়েছি, তবে ওভাররাইড error()করা আমার কাছে একটি ভয়ঙ্কর ধারণা বলে মনে হচ্ছে। এটি একটি ভিন্ন উদ্দেশ্যে পরিবেশন করে, এটি বন্ধুত্বপূর্ণ ব্যবহার বা সহায়তা মুদ্রণের জন্য ডিজাইন করা হয়নি।
পিটারিনো

@ পেটারিনো - ওভাররাইডটি একটি শিশু শ্রেণিতে ঘটছে, সুতরাং এটি কোনও সমস্যা হওয়া উচিত নয়। এটা স্পষ্ট।
মার্সেল উইলসন

1
@ ইউন্টবু ওয়ান্ডারফুল! ঠিক আমার যা প্রয়োজন ছিল। একটি প্রশ্ন, এটি কি সাবকম্যান্ডগুলিতেও প্রয়োগ করা যেতে পারে? আমি সাধারণত মাত্র `` নেমস্পেস (আউটপুট = কিছুই নয়) পাই `` আমি কীভাবে সমস্ত সাবকম্যান্ডে ত্রুটি সহজেই ট্রিগার করতে পারি? আমি সেখানে একটি ত্রুটি ট্রিগার করতে চাই।
জোনাথন কোমার

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)

কোনও যুক্তি ছাড়াই স্ক্রিপ্টটি চালিত হলে পার্স_আর্গস () একটি ত্রুটির প্রতিবেদন করবে।


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

দুর্দান্ত উত্তর! আমি কেবল পরিবর্তনটি পরামিতি ছাড়াই ল্যাম্বদা ব্যবহার করছিলাম।
boh717

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))

যদি ডাব্লু / ও আর্গুমেন্ট বলা হয় এটি সম্পূর্ণ সহায়তা (সংক্ষিপ্ত ব্যবহার নয়) মুদ্রণ করবে।


2
sys.argv[1:]একটি খুব সাধারণ প্রতিমা। আমি parser.parse_args(None if sys.argv[1:] else ['-h'])আরও বুদ্ধিমান এবং ক্লিনার দেখতে পাচ্ছি ।
নুনো আন্দ্রে

1
@ নুনোআন্দ্রা ধন্যবাদ - উত্তরটি আপডেট করেছেন। প্রকৃতপক্ষে আরও অজগর মনে হয়।
আইভজেন পপোভিচ

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 () স্থিতিযুক্ত আর্গুমেন্ট অনুপস্থিত থাকলে প্রস্থান করবে। সুতরাং এটি কেবলমাত্র optionচ্ছিক যুক্তি ব্যবহার করার সময় কাজ করে।
মার্সেল উইলসন

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মান (একটি trailing সম্পর্কে newline নিজেকে অন্তর্ভুক্ত!)।

একটি মতামত উদাহরণ, :)

#!/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

উদাহরণ কল:

$ পাইথন 3 ~ / হেলোরওর্ড.পি; প্রতিধ্বনি $?
ব্যবহার: helloworld.py [-h] [- উদাহরণ]

 উদাহরণস্বরূপ আরগপার্সার ভিত্তিক পাইথন ফাইল

alচ্ছিক যুক্তি:
  -h, - সহায়তা এই বার্তাটি দেখান এবং প্রস্থান করুন
  - উদাহরণ উদাহরণ আর্গুমেন্ট

আমি কী জানি কী ভুল হয়েছে, সম্ভবত অনুপস্থিত - উদাহরণস্বরূপ?
128
$ পাইথন 3 ~ / helloworld.py - উদাহরণ; প্রতিধ্বনি $?
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 টিরও বেশি বিবাদী তর্ক নেই:

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 ...

চিয়ার্স!


আমার মনে হয় আপনি সাবপার্সার বা পারস্পরিকভাবে এক্সক্লুসিভ_গোষ্ঠীটি ব্যবহার করতে আরও সহজ হবেন
টিম ব্রে

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')

আউটপুট:

$ পাইথন 3 a_test.py
ব্যবহার: a_test.py [-h] (- ব্যাচ pay_id | - তালিকা | - সমস্ত)
a_test.py: ত্রুটি: আর্গুমেন্টগুলির মধ্যে একটি - ব্যাচ - তালিকা - সমস্ত প্রয়োজন

এটি কেবলমাত্র প্রাথমিক সহায়তা দেয়। এবং অন্যান্য উত্তরগুলির মধ্যে কিছু আপনাকে সম্পূর্ণ সহায়তা দেবে। তবে কমপক্ষে আপনার ব্যবহারকারীরা জানেন যে তারা করতে পারে h


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কারণ প্রেরণ করবেন, আপনি এটিকে আটকাবেন, এটি দেখুন এবং ... ফেলে দিন।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.