Как сделать из argparse разделенных nargs = '+' из nargs = REMAINDER - PullRequest
4 голосов
/ 08 марта 2020

Я использую argparse для анализа нескольких позиционных аргументов как input, а затем нескольких позиционных аргументов как output. Поскольку количество аргументов не ограничено, я пытаюсь использовать -- в качестве разделителя. Обычно я успешно работал с разделителем --, используя nargs=argparse.REMAINDER, поэтому я попробовал это:

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("input", nargs='+')
parser.add_argument("output", nargs=argparse.REMAINDER)

args = parser.parse_args("input1 input2 -- output1 outpu2".split())
print(args)

Однако все аргументы помещаются в input, и я получаю такой вывод:

Namespace(input=['input1', 'input2', 'output1', 'outpu2'], output=[])

-- правильно потребляется, но не действует как разделитель.

Есть ли способ добиться этого с помощью argparse?

Ответы [ 2 ]

3 голосов
/ 08 марта 2020

Нет, нет. -- используется для отделения именованных («необязательных») аргументов от позиционных аргументов, а не для разделения позиционных аргументов на подсегменты. Вот почему в документах сказано (выделение добавлено; цитата из nargs='*', но нет никакой разницы, за исключением того, что для '+' требуется хотя бы один аргумент):

'*' Все имеющиеся аргументы командной строки являются собрал в список. Обратите внимание, что обычно не имеет большого смысла иметь более одного позиционного аргумента с nargs='*', но возможно несколько дополнительных аргументов с nargs='*'.

Зачем Вы определяете флаг --outputnargs='+' или даже nargs='*') и вызываете свою программу с более явным

input1 input2 --output output1 output2

(используйте короткий флаг, если вам нужно набрать восемь символы.)

2 голосов
/ 08 марта 2020

Вы можете определить пользовательское действие, которое позаботится о разделении набора аргументов, используя (почти) любой понравившийся вам разделитель, на входные и выходные файлы.

import argparse


class PartitionedValues(argparse.Action):
    def __init__(self, *args, delim="+++", **kwargs):
        super().__init__(*args, **kwargs)
        self.delim = delimiter

    def __call__(self, parser, namespace, values, option_string):
        files = namespace.input = []
        namespace.output = []
        for f in values:
            if f == self.delim:
                files = namespace.output
            else:
                files.append(f)


p = argparse.ArgumentParser()
p.add_argument("files", action=PartitionedValues, nargs='+')
args = p.parse_args()
print(args.input)
print(args.output)

Затем вызов, такой как

script.py file1 file2 +++ file3 file4

выдаст

['file1', 'file2']
['file3', 'file4']

в качестве вывода. (Обратите внимание, что сам -- и, по-видимому, все, что начинается с --, вызовет конец обработки для параметра files, поэтому вместо него я использовал +++ в качестве разделителя по умолчанию.)

I также сделал разделитель настраиваемым для каждой опции. Вы можете изменить определение аргумента files на

p.add_argument("files", action=PartitionedValues, delim="+=+", nargs="+")

, а затем вызвать ваш скрипт с помощью

script.py file1 file2 +=+ file3 file4

, чтобы получить тот же вывод.

...