मैं एक सूची को तर्क-वितर्क के साथ कमांड-लाइन तर्क के रूप में कैसे पारित कर सकता हूं?


442

मैं एक कमांड लाइन प्रोग्राम के तर्क के रूप में एक सूची पास करने की कोशिश कर रहा हूं। क्या argparseविकल्प के रूप में एक सूची पास करने का विकल्प है?

parser.add_argument('-l', '--list',
                      type=list, action='store',
                      dest='list',
                      help='<Required> Set flag',
                      required=True)

स्क्रिप्ट को नीचे की तरह कहा जाता है

python test.py -l "265340 268738 270774 270817"

जवाबों:


880

टी एल; डॉ

nargsविकल्प या विकल्प की 'append'सेटिंग का उपयोग करें action(यह निर्भर करता है कि आप उपयोगकर्ता इंटरफ़ेस को कैसे व्यवहार करना चाहते हैं)।

nargs

parser.add_argument('-l','--list', nargs='+', help='<Required> Set flag', required=True)
# Use like:
# python arg.py -l 1234 2345 3456 4567

nargs='+'1 या अधिक तर्क nargs='*'लेता है , शून्य या अधिक लेता है।

संलग्न

parser.add_argument('-l','--list', action='append', help='<Required> Set flag', required=True)
# Use like:
# python arg.py -l 1234 -l 2345 -l 3456 -l 4567

साथ appendउपलब्ध कराने का विकल्प कई बार सूची का निर्माण करने के।

उपयोग न करें type=list!!! - शायद ऐसी कोई स्थिति नहीं है, जहां आप इसके type=listसाथ उपयोग करना चाहते हैं argparse। कभी।


आइए कुछ अलग-अलग तरीकों पर अधिक विस्तार से एक नज़र डालते हैं जो एक ऐसा करने की कोशिश कर सकते हैं, और अंतिम परिणाम।

import argparse

parser = argparse.ArgumentParser()

# By default it will fail with multiple arguments.
parser.add_argument('--default')

# Telling the type to be a list will also fail for multiple arguments,
# but give incorrect results for a single argument.
parser.add_argument('--list-type', type=list)

# This will allow you to provide multiple arguments, but you will get
# a list of lists which is not desired.
parser.add_argument('--list-type-nargs', type=list, nargs='+')

# This is the correct way to handle accepting multiple arguments.
# '+' == 1 or more.
# '*' == 0 or more.
# '?' == 0 or 1.
# An int is an explicit number of arguments to accept.
parser.add_argument('--nargs', nargs='+')

# To make the input integers
parser.add_argument('--nargs-int-type', nargs='+', type=int)

# An alternate way to accept multiple inputs, but you must
# provide the flag once per input. Of course, you can use
# type=int here if you want.
parser.add_argument('--append-action', action='append')

# To show the results of the given option to screen.
for _, value in parser.parse_args()._get_kwargs():
    if value is not None:
        print(value)

यहां वह आउटपुट है जिसकी आप अपेक्षा कर सकते हैं:

$ python arg.py --default 1234 2345 3456 4567
...
arg.py: error: unrecognized arguments: 2345 3456 4567

$ python arg.py --list-type 1234 2345 3456 4567
...
arg.py: error: unrecognized arguments: 2345 3456 4567

$ # Quotes won't help here... 
$ python arg.py --list-type "1234 2345 3456 4567"
['1', '2', '3', '4', ' ', '2', '3', '4', '5', ' ', '3', '4', '5', '6', ' ', '4', '5', '6', '7']

$ python arg.py --list-type-nargs 1234 2345 3456 4567
[['1', '2', '3', '4'], ['2', '3', '4', '5'], ['3', '4', '5', '6'], ['4', '5', '6', '7']]

$ python arg.py --nargs 1234 2345 3456 4567
['1234', '2345', '3456', '4567']

$ python arg.py --nargs-int-type 1234 2345 3456 4567
[1234, 2345, 3456, 4567]

$ # Negative numbers are handled perfectly fine out of the box.
$ python arg.py --nargs-int-type -1234 2345 -3456 4567
[-1234, 2345, -3456, 4567]

$ python arg.py --append-action 1234 --append-action 2345 --append-action 3456 --append-action 4567
['1234', '2345', '3456', '4567']

तकिए :

  • का उपयोग करें nargsयाaction='append'
    • nargsएक उपयोगकर्ता के दृष्टिकोण से अधिक सीधा हो सकता है, लेकिन यह अनपेक्षित हो सकता है यदि स्थिति संबंधी तर्क हैं क्योंकि argparseयह नहीं बता सकता है कि क्या स्थितिगत तर्क होना चाहिए और क्या होना चाहिए nargs; यदि आपके पास स्थिति-संबंधी तर्क हैं, तो action='append'एक बेहतर विकल्प होने का अंत हो सकता है।
    • अगर इसके बाद के संस्करण सच ही है nargsदिया जाता है '*', '+'या '?'। यदि आप एक पूर्णांक संख्या (जैसे 4) प्रदान करते हैं, तो विकल्प nargsऔर स्थिति संबंधी तर्कों के साथ मिश्रण करने में कोई समस्या नहीं argparseहोगी क्योंकि विकल्प के लिए उम्मीद करने के लिए वास्तव में कितने मान होंगे।
  • कमांड लाइन 1 पर उद्धरणों का उपयोग न करें
  • उपयोग न करें type=list, क्योंकि यह सूचियों की एक सूची लौटाएगा
    • ऐसा इसलिए होता है क्योंकि हुड के तहत आपके द्वारा चुने गए प्रत्येक व्यक्ति के तर्क को स्वीकार करने argparseके typeलिए आप सभी तर्कों का समुच्चय नहीं करते हैं।type
    • आप type=int(या जो भी) का उपयोग कर सकते हैं सूची की सूची (या जो कुछ भी)

1 : मैं सामान्य रूप से मतलब नहीं है .. मेरा मतलब है कि एक सूची पासargparse करने के लिए उद्धरणों का उपयोग करना वह नहीं है जो आप चाहते हैं।


3
तार की सूची के बारे में क्या? यह कई स्ट्रिंग तर्क ("ssup", "कुछ" और "अन्य") को उन सूचियों की सूची में बदल देता है जो इस तरह दिखती हैं: [['w', 'a', 's', 's', 'u' , 'p'], '' s ',' o ',' m ',' e ',' t ',' h ',' i ',' n ',' g '], [' e ',' ' l ',' s ',' e ']]
rd108

3
@ rd108 मैं देखता हूं, मैं शर्त लगाता हूं कि आप type=listविकल्प का उपयोग कर रहे हैं । उस का उपयोग न करें। यह एक स्ट्रिंग को एक सूची में बदल देता है, और इसलिए सूचियों की सूची।
सेठमोर्टन

1
जब तक आप typeपैरामीटर को किसी अन्य ऑब्जेक्ट पर सेट नहीं करते हैं, तब तक सभी इनपुट को स्ट्रिंग माना जाता है । डिफ़ॉल्ट रूप से यह विधि स्ट्रिंग्स की एक सूची देता है।
सेठमोर्टन

1
--विभाजित कर सकते हैं विकल्प बनाम स्थिति संबंधी तर्क। prog --opt1 par1 ... -- posp1 posp2 ...

1
यदि कोई स्थितिगत तर्क हैं तो यह अनपेक्षित हो सकता है क्योंकि argparse यह नहीं बता सकता है कि स्थितिगत तर्क क्या होना चाहिए और नर्ग का क्या होना चाहिए--यह जानने में मदद करता है जैसा कि मेरी पिछली टिप्पणी में उदाहरण में दिखाया गया है। IOW उपयोगकर्ता आपूर्ति के --बाद सभी स्थैतिक तर्क।

83

मैं एक सीमांकित स्ट्रिंग पास करना पसंद करता हूं जिसे मैं बाद में स्क्रिप्ट में पार्स करता हूं। इसके कारण हैं; सूची किसी भी प्रकार की हो सकती है , intया strकभी-कभी nargsयदि मैं एक से अधिक वैकल्पिक तर्क और स्थिति-संबंधी तर्क देता हूं , तो मैं समस्याओं में भाग लेता हूं।

parser = ArgumentParser()
parser.add_argument('-l', '--list', help='delimited list input', type=str)
args = parser.parse_args()
my_list = [int(item) for item in args.list.split(',')]

फिर,

python test.py -l "265340,268738,270774,270817" [other arguments]

या,

python test.py -l 265340,268738,270774,270817 [other arguments]

ठीक काम करेगा। सीमांकक एक स्थान हो सकता है, भी, जो प्रश्न में उदाहरण में जैसे तर्क मूल्य के आसपास उद्धरण लागू करेगा।


57
आप पोस्ट-प्रोसेसिंग के बजाय typeतर्क सेट कर सकते हैं । lambda s: [int(time) for item in s.split(',')]args.list
रसोइया

13
@ चेपनर, हाँ आप बिलकुल सही हैं और यह अधिक पायथोनिक होगा - बस एक छोटा टाइपो: int(time)होना चाहिए int(item)। मेरा उदाहरण एक साधारण संस्करण था जो मैं आमतौर पर करता हूं, जहां मैं एक साधारण प्रसंस्करण के बजाय कई अन्य चीजों की जांच करता हूं। लेकिन बस इस सवाल का जवाब देने के लिए, मैं भी आपके रास्ते को और अधिक सुंदर लगता हूं ..
डोजुबा

1
यह उत्तर सबसे अधिक पाइथोनिक लगता है
क्वेटज़लकोटाल

1
@Chepner की टिप्पणी कुछ गंभीर निन्जा
कौशल

1
lambda items: list(csv.reader([items]))[0]मानक सीएसवी पुस्तकालय के साथ मनमाने ढंग से सीएसवी इनपुट के बारे में चिंतित किसी के लिए @chepner से टिप्पणी का एक संशोधित संस्करण है (संदर्भ: @adamk से उत्तर )।
केविन

19

इसके अतिरिक्त nargs, choicesयदि आप पहले से सूची जानते हैं तो आप इसका उपयोग करना चाहते हैं :

>>> parser = argparse.ArgumentParser(prog='game.py')
>>> parser.add_argument('move', choices=['rock', 'paper', 'scissors'])
>>> parser.parse_args(['rock'])
Namespace(move='rock')
>>> parser.parse_args(['fire'])
usage: game.py [-h] {rock,paper,scissors}
game.py: error: argument move: invalid choice: 'fire' (choose from 'rock',
'paper', 'scissors')

10

Argparse के add_argument मेथड में nargs पैरामीटर का उपयोग करना

मैं एक add_argument पैरामीटर के रूप में nargs = ' ' का उपयोग करता हूं यदि मैंने कोई स्पष्ट तर्क नहीं दिया है, तो मैं विशेष रूप से चूक को चुनने के लिए nargs = ' ' विकल्प का उपयोग करता हूं

उदाहरण के लिए एक कोड स्निपेट भी शामिल है:

उदाहरण: temp_args1.py

कृपया ध्यान दें: नीचे नमूना कोड python3 में लिखा गया है। प्रिंट स्टेटमेंट फॉर्मेट को बदलकर, python2 में चला सकते हैं

#!/usr/local/bin/python3.6

from argparse import ArgumentParser

description = 'testing for passing multiple arguments and to get list of args'
parser = ArgumentParser(description=description)
parser.add_argument('-i', '--item', action='store', dest='alist',
                    type=str, nargs='*', default=['item1', 'item2', 'item3'],
                    help="Examples: -i item1 item2, -i item3")
opts = parser.parse_args()

print("List of items: {}".format(opts.alist))

नोट: मैं कई स्ट्रिंग तर्क एकत्र कर रहा हूं जो सूची में संग्रहीत हो जाते हैं - opts.alist यदि आप पूर्णांक की सूची चाहते हैं, तो parser.add_argument पर टाइप पैरामीटर को int में बदलें

निष्पादन परिणाम:

python3.6 temp_agrs1.py -i item5 item6 item7
List of items: ['item5', 'item6', 'item7']

python3.6 temp_agrs1.py -i item10
List of items: ['item10']

python3.6 temp_agrs1.py
List of items: ['item1', 'item2', 'item3']

1
@Py_minion क्या एक तर्क के रूप में सूची का उपयोग करने का एक तरीका है, और सूची के रूप में भी आउटपुट है? temp_args1.py -i [item5 ,item6, item7]और आउटपुट एक सूची के रूप में अच्छी तरह से (नेस्टेड सूची के बजाय) है
मूंदड़ा

@ नमस्कार हाँ। खुशी से आपने पूछा। `` `parser.add_argument ('- o', '--options', action = 'store', dest = 'opt_list', type = str, nargs = '*', default = sample_list, help = = डेटाबेस का स्ट्रिंग सफेद स्थान द्वारा अलग किया गया। उदाहरण: \ -o विकल्प 1 विकल्प 2, -o विकल्प 3 ")` `यहां '' नमूना_सूची 'डिफ़ॉल्ट विकल्पों के साथ सूची का प्रकार है। Ex: sample_list = [option4, option5]
Py_minion

1
@Py_minion धन्यवाद। आज बाद में इसका परीक्षण करने जा रहे हैं।
मूंदड़ा

मैंने इसका उपयोग किया, यह तर्कों से सूची बनाने के लिए बहुत उपयोगी है।
सिबई

5

यदि आप एक एकल स्विच को कई पैरामीटर लेने का इरादा कर रहे हैं, तो आप उपयोग करते हैं nargs='+'। यदि आपका उदाहरण '-l' वास्तव में पूर्णांक ले रहा है:

a = argparse.ArgumentParser()
a.add_argument(
    '-l', '--list',  # either of this switches
    nargs='+',       # one or more parameters to this switch
    type=int,        # /parameters/ are ints
    dest='list',     # store in 'list'.
    default=[],      # since we're not specifying required.
)

print a.parse_args("-l 123 234 345 456".split(' '))
print a.parse_args("-l 123 -l=234 -l345 --list 456".split(' '))

का उत्पादन

Namespace(list=[123, 234, 345, 456])
Namespace(list=[456])  # Attention!

यदि आप एक ही तर्क को कई बार निर्दिष्ट करते हैं, तो डिफ़ॉल्ट क्रिया ( 'store') मौजूदा डेटा को बदल देती है।

वैकल्पिक appendक्रिया का उपयोग करना है:

a = argparse.ArgumentParser()
a.add_argument(
    '-l', '--list',  # either of this switches
    type=int,        # /parameters/ are ints
    dest='list',     # store in 'list'.
    default=[],      # since we're not specifying required.
    action='append', # add to the list instead of replacing it
)

print a.parse_args("-l 123 -l=234 -l345 --list 456".split(' '))

जो पैदा करता है

Namespace(list=[123, 234, 345, 456])

या आप कॉमा से अलग किए गए मानों को पार्स करने के लिए एक कस्टम हैंडलर / एक्शन लिख सकते हैं ताकि आप कर सकें

-l 123,234,345 -l 456

5

में add_argument(), typeकेवल एक कॉल करने योग्य वस्तु है जो स्ट्रिंग और रिटर्न विकल्प मान प्राप्त करता है।

import ast

def arg_as_list(s):                                                            
    v = ast.literal_eval(s)                                                    
    if type(v) is not list:                                                    
        raise argparse.ArgumentTypeError("Argument \"%s\" is not a list" % (s))
    return v                                                                   


def foo():
    parser.add_argument("--list", type=arg_as_list, default=[],
                        help="List of values")

यह करने की अनुमति देगा:

$ ./tool --list "[1,2,3,4]"

ध्यान दें कि यदि किसी को स्ट्रिंग्स पास करने की आवश्यकता होती है, तो इस विधि को कमांड लाइन पर उन्हें उचित रूप से उद्धृत करना होगा। एक उपयोगकर्ता को यह अप्रत्याशित लग सकता है। यदि केवल पूर्णांक को पार्स करते हैं तो यह ठीक है।
सेठमोर्टन

1

यदि आपके पास एक नेस्टेड सूची है जहां आंतरिक सूचियों के विभिन्न प्रकार और लंबाई हैं और आप प्रकार को संरक्षित करना चाहते हैं, उदाहरण के लिए;

[[1, 2], ["foo", "bar"], [3.14, "baz", 20]]

तब आप इस प्रश्न के लिए @ sam-mason द्वारा प्रस्तावित समाधान का उपयोग कर सकते हैं , नीचे दिखाया गया है:

from argparse import ArgumentParser
import json

parser = ArgumentParser()
parser.add_argument('-l', type=json.loads)
parser.parse_args(['-l', '[[1,2],["foo","bar"],[3.14,"baz",20]]'])

जो देता है:

Namespace(l=[[1, 2], ['foo', 'bar'], [3.14, 'baz', 20]])

0

मैं कई सूचियों, पूर्णांक मानों और स्ट्रिंग्स को पास करना चाहता हूं।

सहायक लिंक => पायथन में बैश वैरिएबल कैसे पास करें?

def main(args):
    my_args = []
    for arg in args:
        if arg.startswith("[") and arg.endswith("]"):
            arg = arg.replace("[", "").replace("]", "")
            my_args.append(arg.split(","))
        else:
            my_args.append(arg)

    print(my_args)


if __name__ == "__main__":
    import sys
    main(sys.argv[1:])

आदेश महत्वपूर्ण नहीं है। आप एक सूची पारित करने के लिए चाहते हैं, बस के बीच में के रूप में करते हैं "["और "]और एक अल्पविराम का उपयोग कर उन्हें अलग।

फिर,

python test.py my_string 3 "[1,2]" "[3,4,5]"

आउटपुट => ['my_string', '3', ['1', '2'], ['3', '4', '5']], my_argsचर में तर्क होते हैं।


0

मुझे लगता है कि चेम्बनेर द्वारा बताए अनुसार, एक लैंबडा फ़ंक्शन को "टाइप" करने के लिए सबसे सुरुचिपूर्ण समाधान पास करना है। इसके अतिरिक्त, यदि आप पहले से नहीं जानते हैं कि आपकी सूची का सीमांकक क्या होगा, तो आप पुनर्मिलन के लिए कई सीमांकक भी पास कर सकते हैं:

# python3 test.py -l "abc xyz, 123"

import re
import argparse

parser = argparse.ArgumentParser(description='Process a list.')
parser.add_argument('-l', '--list',
                    type=lambda s: re.split(' |, ', s),
                    required=True,
                    help='comma or space delimited list of characters')

args = parser.parse_args()
print(args.list)


# Output: ['abc', 'xyz', '123']

क्या आपको -lउदाहरण कॉल का मतलब था? कहां -nसे आया?
एंथनी

इसके अलावा, समाधान मेरे लिए पायथन 3.8.2 में काम नहीं करता है। यहाँ कोड है: parser.add_argument('-l', '--list', type = lambda s: re.split('[ ,;]', s))। यहाँ इनपुट है: script.py -l abc xyz, abc\nxyz। अंत में, यहाँ परिणाम है:script.py: error: unrecognized arguments: xyz, abcnxyz
एंथनी

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