عرض رسالة مساعدة مع Python Argparse عندما يتم استدعاء البرنامج النصي دون أي وسيطات

StackOverflow https://stackoverflow.com/questions/4042452

  •  27-09-2019
  •  | 
  •  

سؤال

قد يكون هذا بسيطًا. افترض أن لدي برنامج يستخدم ArgParse لمعالجة وسيطات/خيارات سطر الأوامر. سيقوم ما يلي بطباعة رسالة "المساعدة":

./myprogram -h

أو:

./myprogram --help

ولكن ، إذا قمت بتشغيل البرنامج النصي دون أي حجج على الإطلاق ، فإنه لا يفعل أي شيء. ما أريد أن يفعله هو عرض رسالة الاستخدام عندما يتم استدعاؤها بدون حجج. كيف يتم ذلك؟

هل كانت مفيدة؟

المحلول

هذه الإجابة تأتي من ستيفن بيثارد على مجموعات جوجل. أنا أعيد نشرها هنا لتسهيل الوصول إلى الأشخاص الذين ليس لديهم حساب 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() يطبع إلى stdout افتراضيا. مثل init_js يقترح, ، استعمال parser.print_help(sys.stderr) لطباعة إلى Stderr.

نصائح أخرى

بدلاً من كتابة فصل ، يمكن استخدامه/باستثناء

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

الاتجاه الصعودي هو أن سير العمل أكثر وضوحًا ولا تحتاج إلى فئة كعب. الجانب السلبي هو أن خط "الاستخدام" الأول طبع مرتين.

سيحتاج هذا إلى حجة إلزامية واحدة على الأقل. مع عدم وجود حجج إلزامية ، فإن توفير args صفر على سطر الأوامر صالح.

مع Argparse يمكنك القيام به:

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)

إذا كانت لديك وسيطات يجب تحديدها لتشغيل البرنامج النصي - استخدم مطلوب المعلمة لـ PresumentParser كما هو موضح أدناه:-

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

سيقوم Parse_args () بالإبلاغ عن خطأ إذا تم تشغيل البرنامج النصي دون أي وسيطات.

إذا قمت بربط الوظائف الافتراضية لمحللات (Sub) ، كما هو مذكور أدناه add_subparsers, ، يمكنك ببساطة إضافته كإجراء افتراضي:

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

أضف المحاولة باستثناء إذا قمت برفع استثناءات بسبب الحجج الموضعية المفقودة.

رمي روايتي في الوبر هنا:

import argparse

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

قد تلاحظ parser.exit - أفعل ذلك بشكل أساسي على هذا النحو لأنه يحفظ خط استيراد إذا كان هذا هو السبب الوحيد sys في الملف...

سيكون الحل أنظف هو تمرير الوسيطة الافتراضية يدويًا إذا لم يتم إعطاء أي منها على سطر الأوامر:

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.

هناك زوج من الواحد مع sys.argv[1:] (تعبير بيثون شائع جدًا لإحالة وسيطات سطر الأوامر ، sys.argv[0] اسم البرنامج النصي) الذي يمكنه القيام بالمهمة.

الأول هو التوسيع الذاتي والنظيف والثاني:

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

والثاني هو متسلل قليلا. الجمع بين الحقيقة التي تم تقييمها مسبقًا بأن قائمة فارغة False مع ال True == 1 و False == 0 معادلات تحصل على هذا:

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

ربما الكثير من الأقواس ، ولكن من الواضح تمامًا إذا تم اختيار وسيطة سابقة.

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

ال parser.exit الطريقة تقبل أيضا أ status (الرمز الإرجاع) ، و 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; echo $?
usage: helloworld.py [-h] [--example]

 Example argparser based python file

optional arguments:
  -h, --help  show this help message and exit
  --example   Example Argument

I just don't know what went wrong, maybe missing --example condition?
128
$ python3 ~/helloworld.py --example; echo $?
0

اضبط الوسائط الموضعية الخاصة بك مع NARGS ، وتحقق مما إذا كانت ARGs الموضعية فارغة.

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

المرجعي بيثون نارجز

فيما يلي طريقة أخرى للقيام بذلك ، إذا كنت بحاجة إلى شيء مرن حيث تريد عرض المساعدة إذا تم تمرير معاملات محددة ، لا شيء على الإطلاق أو أكثر من 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 ...

هتافات!

إذا كان أمرك شيئًا يحتاجه المستخدم إلى اختيار بعض الإجراءات ، فاستخدم مجموعة حصرية متبادلة مع مطلوب = صحيح.

هذا نوع من التمديد للإجابة التي قدمها 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] (-دفع pay_id |-list |-كل)
a_test.py: خطأ: إحدى الوسائط -دفعة -قائمة -كل مطلوب

هذا يعطي فقط المساعدة الأساسية. وستمنحك بعض الإجابات الأخرى المساعدة الكاملة. لكن على الأقل يعرف المستخدمون أنهم يستطيعون القيام به

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top