পাইথন আরগপারস: কমপক্ষে একটি যুক্তি প্রয়োজনীয় Make


96

আমি ব্যবহার করছি argparseপাইথন প্রোগ্রাম যা করতে -process, -uploadঅথবা উভয়:

parser = argparse.ArgumentParser(description='Log archiver arguments.')
parser.add_argument('-process', action='store_true')
parser.add_argument('-upload',  action='store_true')
args = parser.parse_args()

কমপক্ষে একটি প্যারামিটার ছাড়াই প্রোগ্রামটি অর্থহীন। আমি কীভাবে argparseকমপক্ষে একটি পরামিতিটি বেছে নিতে বাধ্য করতে কনফিগার করব ?

হালনাগাদ:

মন্তব্য অনুসরণ করে: কমপক্ষে একটি বিকল্প দিয়ে একটি প্রোগ্রামকে প্যারাম্যাট্রাইজ করার পাইথোনিক উপায় কী?


9
-xসর্বজনীনভাবে একটি পতাকা এবং .চ্ছিক। -এটি প্রয়োজন হলে কাটা ।

4
আপনি কি processডিফল্ট আচরণ করতে পারবেন না (কোনও বিকল্প নির্দিষ্ট করার প্রয়োজন ছাড়াই) এবং সেই বিকল্পটি সেট করা uploadথাকলে ব্যবহারকারীকে সেটিতে পরিবর্তনের অনুমতি দিতে পারেন ? সাধারণত, বিকল্পগুলি alচ্ছিক হওয়া উচিত, তাই নাম। প্রয়োজনীয় বিকল্পগুলি এড়ানো উচিত (এটি ডক্সেও রয়েছে)। argparse
টিম পিটজ্যাকার

@ অ্যাডাম্যাটান আপনি আপনার প্রশ্ন জিজ্ঞাসা করে প্রায় তিন বছর হয়ে গেছে তবে আমি এতে চ্যালেঞ্জটি লুকিয়ে থাকতে পছন্দ করেছি এবং এই ধরণের কাজের জন্য নতুন সমাধানগুলির সুবিধাটি ব্যবহার করেছি।
জান ভ্লকিনস্কি

উত্তর:


113
if not (args.process or args.upload):
    parser.error('No action requested, add -process or -upload')

4
এটি সম্ভবত একমাত্র উপায়, যদি argparseএর জন্য কোনও বিল্ট-ইন বিকল্প না থাকে।
আদম মতান

32
args = vars(parser.parse_args())
if not any(args.values()):
    parser.error('No arguments provided.')

4
একটি সাধারণ সমাধানের জন্য +1। এছাড়াও ব্যবহারের মতো vars(), যা ** সহ কোনও নির্মাণকারীর সাবধানে-নামকরণের বিকল্পগুলি পাস করার জন্যও কার্যকর।
লেনা

যা আমি ঠিক তা দিয়ে যাচ্ছি। ধন্যবাদ!
ব্রেন্টল্যান্স

4
ডাং, আমি এটি পছন্দ করি vars। আমি ঠিক করেছি .__dict__এবং আগে বোবা অনুভূত।
থিও বেলারে

4
দুর্দান্ত উত্তর। "ওয়ার্স" এবং "যে কোনও" উভয়ই আমার কাছে নতুন ছিল :-)
বিবেক ঝা

21

যদি 'বা উভয়' অংশ না হয় (আমি প্রথমে এটি মিস করেছি) আপনি এরকম কিছু ব্যবহার করতে পারেন:

parser = argparse.ArgumentParser(description='Log archiver arguments.')
parser.add_argument('--process', action='store_const', const='process', dest='mode')
parser.add_argument('--upload',  action='store_const', const='upload', dest='mode')
args = parser.parse_args()
if not args.mode:
    parser.error("One of --process or --upload must be given")

যদিও, সম্ভবত পরিবর্তে সাব কম্যান্ড ব্যবহার করা ভাল ধারণা হবে।


4
আমি মনে করি তিনি XOR- কে নয়, --processOR কে অনুমতি দিতে চান --upload। এটি একই সাথে উভয় বিকল্প সেট করা থেকে বাধা দেয়।
ফিহাগ

+1 কারণ আপনি সাবকম্যান্ড উল্লেখ করেছেন। তবুও - যেমন কেউ মন্তব্যগুলিতে নির্দেশ করেছে -xএবং --xxxসাধারণত alচ্ছিক পরামিতি।
ম্যাক

20

আমি জানি এটি ময়লা হিসাবে পুরানো, তবে একটি বিকল্পের প্রয়োজন তবে একাধিক (এক্সওআর) নিষিদ্ধ করার উপায়টি এরকম:

parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument('-process', action='store_true')
group.add_argument('-upload',  action='store_true')
args = parser.parse_args()
print args

আউটপুট:

>opt.py  
usage: multiplot.py [-h] (-process | -upload)  
multiplot.py: error: one of the arguments -process -upload is required  

>opt.py -upload  
Namespace(process=False, upload=True)  

>opt.py -process  
Namespace(process=True, upload=False)  

>opt.py -upload -process  
usage: multiplot.py [-h] (-process | -upload)  
multiplot.py: error: argument -process: not allowed with argument -upload  

4
দুর্ভাগ্যক্রমে, ওপি কোনও এক্সওআর চায় না। এটি উভয়ই বা উভয়ই, তবে কোনওটি নয় তাই আপনার শেষ পরীক্ষার কেস তাদের প্রয়োজনীয়তা পূরণ করে না।
kdopen

4
@ কেডোপেন: উত্তরদাতারা স্পষ্ট করে দিয়েছিলেন যে এটি মূল প্রশ্নে একটি প্রকরণ, যা আমি দরকারী বলে মনে করেছি: "এক বিকল্প প্রয়োজন তবে একাধিককে নিষেধ করা যেতে পারে" সম্ভবত স্ট্যাক এক্সচেঞ্জের শিষ্টাচার পরিবর্তে একটি নতুন প্রশ্নের জন্য ডাকবে । তবে এই উত্তরটি এখানে উপস্থিত করা আমাকে সহায়তা করেছে ...
এরিক.ওয়েথারস

4
এই পোস্টটি প্রাথমিক প্রশ্নের উত্তর নেই
মার্ক

4
এটি "কমপক্ষে একজনের" প্রশ্নের উত্তর কীভাবে দেয়?
xaxxon

4
দুর্ভাগ্যক্রমে, ওপি কোনও এক্সওআর চায় না।
duckman_1991

8

প্রয়োজনীয়তা পর্যালোচনা

  • ব্যবহার argparse(আমি এটিকে উপেক্ষা করব)
  • এক বা দুটি ক্রিয়া কল করার অনুমতি দিন (কমপক্ষে একটি প্রয়োজনীয়)।
  • পাইথোনিক দ্বারা চেষ্টা করুন (আমি বরং এটি "পসিক্স" -র মতো বলব)

কমান্ড লাইনে থাকার সময় কিছু অন্তর্নিহিত প্রয়োজনীয়তাও রয়েছে:

  • ব্যবহারকারীর কাছে এমনভাবে ব্যবহারটি ব্যাখ্যা করুন যা বোঝা সহজ
  • বিকল্পগুলি alচ্ছিক হতে হবে
  • পতাকা এবং বিকল্পগুলি নির্দিষ্ট করার অনুমতি দিন
  • অন্যান্য পরামিতিগুলির সাথে সংযুক্ত করার অনুমতি দিন (যেমন ফাইলের নাম বা নাম)।

docopt(ফাইল managelog.py) ব্যবহার করে নমুনা সমাধান :

"""Manage logfiles
Usage:
    managelog.py [options] process -- <logfile>...
    managelog.py [options] upload -- <logfile>...
    managelog.py [options] process upload -- <logfile>...
    managelog.py -h

Options:
    -V, --verbose      Be verbose
    -U, --user <user>  Username
    -P, --pswd <pswd>  Password

Manage log file by processing and/or uploading it.
If upload requires authentication, you shall specify <user> and <password>
"""
if __name__ == "__main__":
    from docopt import docopt
    args = docopt(__doc__)
    print args

এটি চালানোর চেষ্টা করুন:

$ python managelog.py
Usage:
    managelog.py [options] process -- <logfile>...
    managelog.py [options] upload -- <logfile>...
    managelog.py [options] process upload -- <logfile>...
    managelog.py -h

সহায়তাটি দেখান:

$ python managelog.py -h
Manage logfiles
Usage:
    managelog.py [options] process -- <logfile>...
    managelog.py [options] upload -- <logfile>...
    managelog.py [options] process upload -- <logfile>...
    managelog.py -h

Options:
    -V, --verbose      Be verbose
    -U, --user <user>  Username
    -P, --pswd <pswd>  P    managelog.py [options] upload -- <logfile>...

Manage log file by processing and/or uploading it.
If upload requires authentication, you shall specify <user> and <password>

এবং এটি ব্যবহার করুন:

$ python managelog.py -V -U user -P secret upload -- alfa.log beta.log
{'--': True,
 '--pswd': 'secret',
 '--user': 'user',
 '--verbose': True,
 '-h': False,
 '<logfile>': ['alfa.log', 'beta.log'],
 'process': False,
 'upload': True}

সংক্ষিপ্ত বিকল্প short.py

আরও ছোট আকারের হতে পারে:

"""Manage logfiles
Usage:
    short.py [options] (process|upload)... -- <logfile>...
    short.py -h

Options:
    -V, --verbose      Be verbose
    -U, --user <user>  Username
    -P, --pswd <pswd>  Password

Manage log file by processing and/or uploading it.
If upload requires authentication, you shall specify <user> and <password>
"""
if __name__ == "__main__":
    from docopt import docopt
    args = docopt(__doc__)
    print args

ব্যবহার এর মতো দেখাচ্ছে:

$ python short.py -V process upload  -- alfa.log beta.log
{'--': True,
 '--pswd': None,
 '--user': None,
 '--verbose': True,
 '-h': False,
 '<logfile>': ['alfa.log', 'beta.log'],
 'process': 1,
 'upload': 1}

দ্রষ্টব্য, "প্রক্রিয়া" এবং "আপলোড" কীগুলির জন্য বুলিয়ান মানগুলির পরিবর্তে কাউন্টার রয়েছে।

দেখা যাচ্ছে, আমরা এই শব্দগুলির সদৃশ প্রতিরোধ করতে পারি না:

$ python short.py -V process process upload  -- alfa.log beta.log
{'--': True,
 '--pswd': None,
 '--user': None,
 '--verbose': True,
 '-h': False,
 '<logfile>': ['alfa.log', 'beta.log'],
 'process': 2,
 'upload': 1}

সিদ্ধান্তে

ভাল কমান্ড লাইন ইন্টারফেস ডিজাইন কখনও কখনও চ্যালেঞ্জ হতে পারে।

কমান্ড লাইন ভিত্তিক প্রোগ্রামের একাধিক দিক রয়েছে:

  • কমান্ড লাইন ভাল ডিজাইন
  • সঠিক পার্সার নির্বাচন / ব্যবহার করা

argparse অনেক প্রস্তাব দেয়, তবে সম্ভাব্য পরিস্থিতিগুলিকে সীমাবদ্ধ করে এবং খুব জটিল হয়ে উঠতে পারে।

সঙ্গে docoptকিছু অনেক খাটো যখন পাঠযোগ্যতা সংরক্ষণের এবং নমনীয়তা উচ্চ ডিগ্রী প্রস্তাব যান। আপনি যদি অভিধান থেকে পার্স করা যুক্তিগুলি পরিচালনা করতে এবং ম্যানুয়ালি (বা অন্য লাইব্রেরি দ্বারা আহৃত) রূপান্তরগুলি (পূর্ণসংখ্যায়, ফাইলগুলি খোলার জন্য schema) কিছু করেন তবে আপনি docoptকমান্ড লাইন পার্সিংয়ের জন্য উপযুক্ত find


ডকোপ্টের কথা কখনও শুনেনি, দুর্দান্ত পরামর্শ!
টন ভ্যান ড্যান হিউভেল

নিবন্ধন করুন আমি কেবল নিশ্চিত করতে চাই, আমি এখনও এটি কমান্ড লাইন ইন্টারফেসের জন্য আমার পছন্দসই সমাধান হিসাবে ব্যবহার করছি।
জান ভ্লকিনস্কি

সেরা উত্তর পরিষ্কার, বিস্তারিত উদাহরণের জন্য আপনাকে ধন্যবাদ।
jnovack

5

আপনি অন্তত একটি পরামিতি সহ চালানোর জন্য একটি পাইথন প্রোগ্রাম প্রয়োজন হয়, একটি আর্গুমেন্ট যে যোগ করে না (- বা - ডিফল্ট অনুসারে) বিকল্প উপসর্গ আছে এবং সেট nargs=+(এক যুক্তির নূন্যতম প্রয়োজন)। এই পদ্ধতির যে সমস্যাটি আমি পেয়েছি তা হ'ল আপনি যদি যুক্তিটি নির্দিষ্ট না করেন তবে আরগপার্স একটি "খুব অল্প কিছু যুক্তি" ত্রুটি উত্পন্ন করবে এবং সহায়তা মেনুটি প্রিন্ট করবে না। আপনার যদি সেই কার্যকারিতাটির প্রয়োজন না হয় তবে কোডে এটি কীভাবে করবেন তা এখানে রয়েছে:

import argparse

parser = argparse.ArgumentParser(description='Your program description')
parser.add_argument('command', nargs="+", help='describe what a command is')
args = parser.parse_args()

আমি মনে করি যে আপনি যখন বিকল্প উপসর্গের সাথে একটি যুক্তি যুক্ত করেন, তখন নার্গগুলি কেবলমাত্র বিকল্পটি নয়, পুরো আর্গুমেন্ট পার্সারকে পরিচালনা করে। (আমার অর্থ হ'ল, যদি আপনার --optionসাথে পতাকা থাকে nargs="+"তবে --optionপতাকা কমপক্ষে একটি যুক্তি প্রত্যাশা করে you যদি আপনার optionসাথে থাকে তবে nargs="+"এটি কমপক্ষে একটি যুক্তি সামগ্রিকভাবে প্রত্যাশা করে))


আপনি choices=['process','upload']যে যুক্তি যুক্ত করতে পারে।
এইচপলজ

5

জন্য http://bugs.python.org/issue11588 আমি সরলীকরণ পথ অন্বেষণ করছি mutually_exclusive_groupভালো ক্ষেত্রেই হ্যান্ডেল ধারণা।

এই বিকাশের সাথে argparse.py, https://github.com/hpaulj/argparse_issues/blob/nested/argparse.py আমি লিখতে সক্ষম:

parser = argparse.ArgumentParser(prog='PROG', 
    description='Log archiver arguments.')
group = parser.add_usage_group(kind='any', required=True,
    title='possible actions (at least one is required)')
group.add_argument('-p', '--process', action='store_true')
group.add_argument('-u', '--upload',  action='store_true')
args = parser.parse_args()
print(args)

যা নিম্নলিখিত উত্পাদন করে help:

usage: PROG [-h] (-p | -u)

Log archiver arguments.

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

possible actions (at least one is required):
  -p, --process
  -u, --upload

এটি '-u', '-আপ', '--প্রোক - আপ' ইত্যাদির মতো ইনপুট গ্রহণ করে

এটি https://stackoverflow.com/a/6723066/901925 এর অনুরূপ একটি পরীক্ষা চালানো শেষ করে যদিও ত্রুটির বার্তাটি আরও পরিষ্কার করা দরকার:

usage: PROG [-h] (-p | -u)
PROG: error: some of the arguments process upload is required

আমি অবাক:

  • প্যারামিটারগুলি কি kind='any', required=Trueযথেষ্ট পরিষ্কার (গ্রুপের কোনওটি গ্রহণ করুন; কমপক্ষে একটি প্রয়োজনীয়)?

  • ব্যবহার কি (-p | -u)পরিষ্কার? একটি প্রয়োজনীয় মিউচুয়ালি_ এক্সক্লুসিভ_গ্রুপ একই জিনিস উত্পাদন করে। কিছু বিকল্প স্বরলিপি আছে?

  • এই জাতীয় গোষ্ঠীটি কি phihag'sসাধারণ পরীক্ষার চেয়ে আরও স্বজ্ঞাত ?


আমি add_usage_groupএই পৃষ্ঠায় কোন উল্লেখ খুঁজে পাচ্ছি না : docs.python.org/2/library/argparse.html ; আপনি কি এটির জন্য ডকুমেন্টেশনের লিঙ্ক সরবরাহ করবেন?
পি। মায়ার নূর

@ পি.মায়ারনোর, আমি একটি উত্তর সরবরাহ করেছি - এই উত্তরটির শুরুতে। এটি উত্পাদন করা হয়নি।
এইচপিউলজ

5

এটি করার সর্বোত্তম উপায় হ'ল পাইথন ইনবিল্ট মডিউল অ্যাড_মুটিউলি_ এক্সক্লুসিভ_গ্রুপ ব্যবহার করে ।

parser = argparse.ArgumentParser(description='Log archiver arguments.')
group = parser.add_mutually_exclusive_group()
group.add_argument('-process', action='store_true')
group.add_argument('-upload',  action='store_true')
args = parser.parse_args()

আপনি যদি কেবল একটি যুক্তি কমান্ড লাইনের দ্বারা নির্বাচিত করতে চান তবে প্রয়োজন = গ্রুপের পক্ষে আর্গুমেন্ট হিসাবে সত্য

group = parser.add_mutually_exclusive_group(required=True)

4
এটি আপনাকে "কমপক্ষে একজন" কীভাবে পেয়েছে - এটি আপনাকে "ঠিক এক" পায় না?
xaxxon

4
দুর্ভাগ্যক্রমে, ওপি কোনও এক্সওআর চায় না। ওপি অনুসন্ধান করছে OR
duckman_1991

এটি ওপির প্রশ্নের উত্তর দেয়নি, তবে এটি আমার উত্তর দিয়েছে তাই যাইহোক ধন্যবাদ ¯_ (ツ) _ / ¯
রসটেক্স

2

হয়তো সাব-পার্সার ব্যবহার করবেন?

import argparse

parser = argparse.ArgumentParser(description='Log archiver arguments.')
subparsers = parser.add_subparsers(dest='subparser_name', help='sub-command help')
parser_process = subparsers.add_parser('process', help='Process logs')
parser_upload = subparsers.add_parser('upload', help='Upload logs')
args = parser.parse_args()

print("Subparser: ", args.subparser_name)

এখন --helpদেখায়:

$ python /tmp/aaa.py --help
usage: aaa.py [-h] {process,upload} ...

Log archiver arguments.

positional arguments:
  {process,upload}  sub-command help
    process         Process logs
    upload          Upload logs

optional arguments:
  -h, --help        show this help message and exit
$ python /tmp/aaa.py
usage: aaa.py [-h] {process,upload} ...
aaa.py: error: too few arguments
$ python3 /tmp/aaa.py upload
Subparser:  upload

আপনি এই সাব-পার্সারগুলিতে অতিরিক্ত বিকল্পগুলিও যুক্ত করতে পারেন। এছাড়াও এটির পরিবর্তে dest='subparser_name'আপনি প্রদত্ত সাব-কমান্ডে ডকুমেন্টগুলি সরাসরি কল করতে ফাংশনগুলিকেও আবদ্ধ করতে পারেন।


2

এটি উদ্দেশ্য অর্জন করে এবং এটি আরগপার্স অটোজেনারেটেড --helpআউটপুটটিতেও পুনরায় সংযুক্ত হবে, যা বেশিরভাগ বুদ্ধিমান প্রোগ্রামাররা চান ( এটি optionচ্ছিক যুক্তিগুলির সাথেও কাজ করে):

parser.add_argument(
    'commands',
    nargs='+',                      # require at least 1
    choices=['process', 'upload'],  # restrict the choice
    help='commands to execute'
)

এটিতে অফিসিয়াল ডক্স: https://docs.python.org/3/library/argparse.html#choice


1

ক্রিয়াকলাপের তালিকায় append_const ব্যবহার করুন এবং তারপরে তালিকাটি পপুলেটেড রয়েছে কিনা তা পরীক্ষা করুন:

parser.add_argument('-process', dest=actions, const="process", action='append_const')
parser.add_argument('-upload',  dest=actions, const="upload", action='append_const')

args = parser.parse_args()

if(args.actions == None):
    parser.error('Error: No actions requested')

এমনকি আপনি ধ্রুবকগুলির মধ্যে সরাসরি পদ্ধতিগুলি নির্দিষ্ট করতে পারেন।

def upload:
    ...

parser.add_argument('-upload',  dest=actions, const=upload, action='append_const')
args = parser.parse_args()

if(args.actions == None):
    parser.error('Error: No actions requested')

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