簡體   English   中英

Python和argparse的多個位置參數

[英]Multiple positional arguments with Python and argparse

我正在嘗試使用argparse來解析我正在處理的程序的命令行參數。 本質上,我需要支持在可選參數中傳播的多個位置參數,但是在這種情況下無法使argparse工作。 在實際的程序中,我正在使用自定義操作(我需要在每次找到位置參數時存儲命名空間的快照),但我可以使用append操作復制我遇到的問題:

>>> import argparse
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('-a', action='store_true')
>>> parser.add_argument('-b', action='store_true')
>>> parser.add_argument('input', action='append')
>>> parser.parse_args(['fileone', '-a', 'filetwo', '-b', 'filethree'])
usage: ipython [-h] [-a] [-b] input
ipython: error: unrecognized arguments: filetwo filethree

我希望這導致命名空間(a=True, b=True, input=['fileone', 'filetwo', 'filethree']) ,但是看不出怎么做 - 如果它確實可以。 如果有可能的話,我在文檔或谷歌中看不到任何一種說法,盡管它很可能(很可能?)我忽略了一些東西。 有沒有人有什么建議?

您不能以這種方式將開關(即-a-b )與位置參數(即fileone,filetwo和filethree)交錯。 開關必須出現在位置參數之前或之后,而不是介於兩者之間。

此外,為了擁有多個位置參數,您需要將nargs參數指定為add_argument 例如:

parser.add_argument('input', nargs='+')

這告訴argparse使用一個或多個位置參數並將它們附加到列表中。 有關更多信息,請參閱argparse文檔 有了這一行,代碼:

parser.parse_args(['-a', '-b', 'fileone', 'filetwo', 'filethree'])

結果是:

Namespace(a=True, b=True, input=['fileone', 'filetwo', 'filethree'])

srgerg對位置論證的定義是正確的。 為了獲得您想要的結果,您必須接受它們作為可選參數,並根據您的需要修改結果命名空間。

您可以使用自定義操作:

class MyAction(argparse.Action):
    def __call__(self, parser, namespace, values, option_string=None):

        # Set optional arguments to True or False
        if option_string:
            attr = True if values else False
            setattr(namespace, self.dest, attr)

        # Modify value of "input" in the namespace
        if hasattr(namespace, 'input'):
            current_values = getattr(namespace, 'input')
            try:
                current_values.extend(values)
            except AttributeError:
                current_values = values
            finally:
                setattr(namespace, 'input', current_values)
        else:
            setattr(namespace, 'input', values)

parser = argparse.ArgumentParser()
parser.add_argument('-a', nargs='+', action=MyAction)
parser.add_argument('-b', nargs='+', action=MyAction)
parser.add_argument('input', nargs='+', action=MyAction)

這就是你得到的:

>>> parser.parse_args(['fileone', '-a', 'filetwo', '-b', 'filethree'])
Namespace(a=True, b=True, input=['fileone', 'filetwo', 'filethree'])

或者您可以像這樣修改結果命名空間:

>>> import argparse
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('-a', nargs='+')
>>> parser.add_argument('-b', nargs='+')
>>> parser.add_argument('input', nargs='+')
>>> result = parser.parse_args(['fileone', '-a', 'filetwo', '-b', 'filethree'])

>>> inputs = []
>>> inputs.extend(result.a)
>>> inputs.extend(result.b)
>>> inputs.extend(result.input)

>>> modified = argparse.Namespace(
        a = result.a != [],
        b = result.b != [],
        input = inputs)

這就是你得到的:

>>> modified
Namespace(a=True, b=True, input=['filetwo', 'filethree', 'fileone'])

但是,這兩種方法都會導致代碼的可讀性和可維護性降低。 也許最好更改程序邏輯並以不同的方式執行。

通過可選的“附加”動作更有意義:

parser.add_argument('-i', '--input',action='append')
parser.parse_args(['-i','fileone', '-a', '-i','filetwo', '-b', '-i','filethree'])

您可以使用單獨的位置('input1 -a input2 -b input3')交錯選項,但不能在一個多項位置內交錯選項。 但是你可以通過兩步解析來完成這個任務。

import argparse
parser1 = argparse.ArgumentParser()
parser1.add_argument('-a', action='store_true')
parser1.add_argument('-b', action='store_true')
parser2 = argparse.ArgumentParser()
parser2.add_argument('input', nargs='*')

ns, rest = parser1.parse_known_args(['fileone', '-a', 'filetwo', '-b', 'filethree'])
# Namespace(a=True, b=True), ['fileone', 'filetwo', 'filethree']

ns = parser2.parse_args(rest, ns)
# Namespace(a=True, b=True, input=['fileone', 'filetwo', 'filethree'])

http://bugs.python.org/issue14191是一個建議的補丁,只需調用一次即可完成此操作:

parser.parse_intermixed_args(['fileone', '-a', 'filetwo', '-b', 'filethree'])

在我看來,hpaulj在正確的軌道上,但使事情變得比必要的復雜。 我懷疑Blair正在尋找類似於舊的optparse模塊的行為的東西,並且不需要args對象的輸入字段中的輸入參數列表。 他只是想要

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-a', action='store_true')
parser.add_argument('-b', action='store_true')
opts, args = parser.parse_known_args(['fileone', '-a', 'filetwo', '-b', 'filethree'])
# Namespace(a=True, b=True), ['fileone', 'filetwo', 'filethree']

在optparse的白話中,opts中提供了“選項”,並且可能穿插其他“參數”的列表在args中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM